Non-Fatal Error w aplikacjach mobilnych — istota, rodzaje i obsługa błędów

Autor: IT Sectr Opublikowano: 2026-05-27 Czas czytania: 8 min

Non-Fatal Error — to błąd, który nie powoduje zakończenia działania aplikacji i pozwala kontynuować wykonywanie programu. W przeciwieństwie do fatal error, błędy niekrytyczne mogą zostać przechwycone, obsłużone i zalogowane bez utraty sesji użytkownika. Według danych Firebase Crashlytics Documentation, 2024, około 70% wszystkich zarejestrowanych błędów w aplikacjach produkcyjnych to błędy niekrytyczne, ale ich ignorowanie prowadzi do narastania długu technicznego i stopniowego pogarszania doświadczenia użytkownika. Prawidłowa obsługa błędów non-fatal to jedna z kluczowych umiejętności programisty mobilnego.

Najważniejsze

  • Non-Fatal Error — błąd, który nie kończy działania aplikacji i pozwala na przywrócenie wykonania
  • Obsługa błędów niekrytycznych obejmuje try-catch, logowanie i wyświetlanie fallback UI
  • Logowanie błędów non-fatal jest krytycznie ważne do wykrywania ukrytych błędów w production
  • Fatal Error — przeciwieństwo: błąd powodujący crash aplikacji bez możliwości przywrócenia
  • Crashlytics i Sentry umożliwiają śledzenie błędów non-fatal w czasie rzeczywistym

Czym jest Non-Fatal Error

Non-Fatal Error — to wyjątek lub stan błędny, który nie powoduje zakończenia procesu. Aplikacja nadal działa, ale może znajdować się w nieprawidłowym stanie: dane nie zostały załadowane, żądanie nie zostało wysłane, element interfejsu nie został wyświetlony. Użytkownik albo nie zauważa błędu, albo widzi komunikat i kontynuuje korzystanie z aplikacji.

Kluczowe cechy

Błąd niekrytyczny zawsze pozostawia programowi ścieżkę do przywrócenia. Procedura obsługi błędów może zaproponować alternatywne dane, ponowić operację lub pokazać zastępczy interfejs. Głównym zadaniem jest niedopuszczenie do crasha i utrzymanie doświadczenia użytkownika na akceptowalnym poziomie. Programista musi jawnie przewidzieć scenariusz przywrócenia w każdym bloku catch.

Rola w stabilności aplikacji

Według danych Instabug 2024, 65% użytkowników usuwa aplikację po dwóch nieudanych interakcjach. Błędy non-fatal pozostawione bez uwagi kumulują się i obniżają ogólną jakość działania. Systematyczne logowanie i naprawianie błędów niekrytycznych to bezpośrednia droga do zwiększenia retention i poprawy ocen użytkowników w sklepach z aplikacjami.

Rodzaje błędów niekrytycznych

Błędy sieciowe — najczęstszy typ błędów non-fatal w aplikacjach mobilnych. Limit czasu połączenia, utrata sieci, nieprawidłowy kod statusu serwera — wszystkie te sytuacje są przechwytywane i obsługiwane bez crasha. Użytkownikowi wyświetlany jest komunikat o niedostępności usługi z propozycją ponowienia próby. Dla błędów sieciowych typowy jest wzorzec retry z wykładniczym opóźnieniem.

Błędy walidacji danych

Nieprawidłowy format odpowiedzi serwera, brak obowiązkowego pola, nieprawidłowy typ danych — błędy parsowania są niekrytyczne, jeśli aplikacja prawidłowo obsługuje nieprawidłowe dane. Typowym podejściem jest użycie domyślnych wartości zastępczych i logowanie błędu parsowania z kontekstem żądania do późniejszej analizy na serwerze.

Błędy renderowania UI

Problemy z ładowaniem obrazów, nieprawidłowe czcionki, błędy w layoutach — wszystkie nie są krytyczne, ale pogarszają wrażenia użytkownika. Obrazy zastępcze i wartości fallback pozwalają uniknąć pustych ekranów i czynią błędy mniej zauważalnymi. W React Native do błędów UI używa się Error Boundary z wyświetleniem komponentu zastępczego.

Błędy logiki biznesowej i stanu

Błędy w obliczeniach, niezgodność stanów, nieprawidłowe przejścia między ekranami — błędy logiczne często nie prowadzą do crasha, ale powodują nieprawidłowe działanie aplikacji. Są trudniejsze do wykrycia bez systematycznego logowania i monitorowania, ponieważ nie generują raportów crasha i pozostają niezauważone aż do skargi użytkownika.

Non-Fatal Error vs Fatal Error: porównanie

Non-Fatal Error różni się od fatal tym, że pozostawia programowi możliwość kontynuowania pracy. Fatal error — to stan, z którego aplikacja nie może się przywrócić: dereferencja null-owskaznika, przepełnienie stosu, brak pamięci. Błąd non-fatal można przechwycić, obsłużyć i kontynuować wykonanie, podczas gdy fatal error wymaga ponownego uruchomienia aplikacji.

CechaNon-Fatal ErrorFatal Error
Zakończenie aplikacjiNieTak
Możliwość przywróceniaTak, przez blok catchNie
LogowanieZ kodu przez recordExceptionTylko przez raporter crasha
Wpływ na UXTymczasowa niedogodnośćCałkowita utrata sesji
PrzykładNetwork timeout, parse errorNullPointerException, OOM

Granica między non-fatal a fatal może zależeć od implementacji. Limit czasu sieci w jednej aplikacji jest obsługiwany jako non-fatal (ponowienie żądania po 1–2 sekundach), w innej może być fatalny (crash przy braku procedury obsługi). Jakościowa obsługa błędów zamienia potencjalnie fatalne sytuacje w niekrytyczne, zwiększając stabilność aplikacji. Projektowanie systemu obsługi błędów to jedno z kluczowych zadań architektonicznych przy tworzeniu aplikacji mobilnej z wysokimi wymaganiami niezawodnościowymi. Wbudowany system monitorowania pozwala zespołowi szybko wykrywać i usuwać błędy niekrytyczne, zanim wpłyną one na znaczną liczbę użytkowników.

Logowanie błędów non-fatal

Firebase Crashlytics — główne narzędzie do logowania błędów niekrytycznych w aplikacjach mobilnych. Metoda recordException pozwala zarejestrować wyjątek non-fatal z pełnym stosem wywołań i kontekstem wykonania, nie przerywając działania aplikacji. W przeciwieństwie do raportów crasha, recordException można wywołać w dowolnym miejscu kodu do logowania przechwyconych wyjątków.

kotlin
fun fetchUserData(userId: String) {
    try {
        val response = apiService.getUser(userId)
        updateUI(response)
    } catch (e: IOException) {
        Crashlytics.log("Network error for user $userId")
        Crashlytics.recordException(e)
        showRetryDialog()
    } catch (e: JsonParseException) {
        // Non-fatal: używamy danych zastępczych
        Crashlytics.recordException(e)
        showFallbackContent()
    }
}

// Logowanie z kluczami użytkownika
Crashlytics.setCustomKey("screen", "Profile")
Crashlytics.setCustomKey("api_version", "v3")

Sentry — alternatywa dla Crashlytics z bardziej szczegółową diagnostyką błędów non-fatal. Sentry SDK udostępnia metodę captureException, która wysyła szczegóły wyjątku na serwer. Kluczową zaletą Sentry jest grupowanie podobnych błędów non-fatal w jedno issue, analiza częstotliwości występowania i kontekst wykonania w postaci breadcrumbs — sekwencji działań użytkownika przed błędem.

Kryteria logowania błędów non-fatal

Nie wszystkie błędy non-fatal należy logować. Oczekiwane stany — brak sieci przy braku połączenia — można logować wybiórczo. Nieoczekiwane błędy — NullPointerException w obsłużonym kodzie, nieprawidłowy format danych, logic error — powinny być logowane zawsze. Każdy zespół określa próg istotności: średnio od 10 do 20 unikalnych błędów non-fatal na 1000 użytkowników dziennie uważa się za normę. Ważne jest skonfigurowanie alertów na gwałtowny wzrost liczby błędów non-fatal — może to wskazywać na problemy z nową wersją API lub regresję po wydaniu.

Obsługa błędów non-fatal w kodzie

Podstawowym mechanizmem obsługi jest try-catch, który przechwytuje wyjątek i wykonuje kod przywracania. Dla operacji sieciowych typowym wzorcem jest ponowienie żądania z wykładniczym opóźnieniem (retry with backoff). Dla błędów parsowania — użycie domyślnych wartości zastępczych i logowanie kontekstu do późniejszej analizy po stronie serwera.

swift
func loadImage(from url: URL) -> UIImage? {
    do {
        let data = try Data(contentsOf: url)
        return UIImage(data: data)
    } catch {
        Logger.shared.logError(error: "Image load failed: \(url)")
        return UIImage(named: "placeholder")
    }
}

func performRequest() async throws -> Data {
    var lastError: Error? = nil
    for attempt in 0..<3 {
        do {
            return try await URLSession.shared.data(from: url)
        } catch {
            lastError = error
            try await Task.sleep(UInt64(pow(2, attempt)) * 1_000_000_000)
        }
    }
    throw lastError ?? URLError(.unknown)
}

Typy Result — alternatywne podejście bez wyjątków. Funkcja zwraca sealed class Result z wariantami Success i Failure. Kod wywołujący jawnie obsługuje oba warianty, co eliminuje nieobsłużone błędy. Typy Result są popularne w Kotlin (Result w bibliotece standardowej) i Swift (Result) do jawnej obsługi stanów non-fatal na poziomie typów.

Strategie fallback dla błędów non-fatal

Dla każdego typu błędu non-fatal należy przewidzieć strategię przywracania: ładowanie danych z cache przy błędzie sieciowym, użycie domyślnych wartości przy błędzie parsowania, ponowna inicjalizacja komponentu przy błędzie UI. Dobrą praktyką jest wyświetlenie użytkownikowi toasta lub snackbara z komunikatem o błędzie, ale nie blokowanie całkowicie interakcji z aplikacją. Ważne jest rozróżnianie błędów recoverable (do przywrócenia) i non-recoverable — dla tych drugich strategia przywracania będzie inna, na przykład propozycja ponownego uruchomienia ekranu lub wyczyszczenia danych. Buforowanie poprzedniego udanego stanu często okazuje się najprostszym i najbardziej efektywnym sposobem obsługi błędów non-fatal na platformach mobilnych.

Często zadawane pytania

Czym różni się błąd non-fatal od warning?

Warning — to ostrzeżenie kompilatora lub analizatora statycznego o potencjalnym problemie w kodzie. Non-fatal error — to wyjątek runtime, który już wystąpił, ale nie doprowadził do crasha. Warning można usunąć przed kompilacją, non-fatal error — obsłużyć podczas wykonania przez blok catch.

Czy należy logować wszystkie błędy non-fatal?

Nie, nadmierne logowanie zaśmieca monitoring. Warto logować nieoczekiwane błędy w production i ignorować oczekiwane stany: brak sieci przy braku połączenia loguje się wybiórczo, a NullPointerException w obsłużonym kodzie — zawsze. Każdy zespół określa próg istotności w zależności od kontekstu aplikacji.

Jak obsłużyć błąd non-fatal w SwiftUI?

W SwiftUI używa się ObservableObject z polem @Published errorState do śledzenia stanu błędu. View subskrybuje zmiany i wyświetla alternatywną treść. Przed iOS 17 stosowano Combine z procedurami obsługi, od iOS 17 — SwiftData i makra @Observable do reaktywnej aktualizacji UI.

Czy błąd non-fatal może stać się fatal?

Tak, jeśli błąd wywołuje reakcję łańcuchową. Przykład: niekrytyczny błąd ładowania obrazu może prowadzić do nieprawidłowego stanu UI, który następnie powoduje crash przy próbie wyświetlenia. Jakościowa obsługa błędów non-fatal na każdym poziomie zapobiega ich eskalacji do poziomu fatalnego.

Jak różni się non-fatal w iOS i Android?

W iOS błędy non-fatal są obsługiwane przez do-catch z throw, w Android — przez try-catch z wyjątkami. iOS używa NSError z domenami i kodami błędów, Android — wyjątków Java/Kotlin. Crashlytics działa tak samo na obu platformach przez recordException, zapewniając jednolity interfejs do monitorowania.

Podsumowanie

  • Non-Fatal Error — błąd runtime, niekończący aplikacji i dopuszczający przywrócenie wykonania
  • Błędy sieciowe, błędy parsowania i renderowania UI — trzy główne klasy błędów niekrytycznych
  • Fatal Error — przeciwieństwo non-fatal, powodujące całkowity crash aplikacji bez przywrócenia
  • Crashlytics i Sentry — główne narzędzia logowania błędów non-fatal w production
  • Typy Result — alternatywa dla wyjątków do jawnej obsługi stanów błędnych na poziomie typów
  • Wartości zastępcze i strategie fallback zapobiegają widocznemu pogorszeniu doświadczenia użytkownika
  • Systematyczne naprawianie błędów non-fatal zwiększa retention i jakość aplikacji według Instabug

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również