Non-Fatal Error — este o eroare care nu duce la încheierea funcționării aplicației și permite continuarea execuției programului. Spre deosebire de fatal error, erorile nefatale pot fi interceptate, gestionate și logate fără pierderea sesiunii utilizatorului. Potrivit Firebase Crashlytics Documentation, 2024, aproximativ 70% din toate erorile înregistrate în aplicațiile de producție sunt nefatale, dar ignorarea lor duce la acumularea datoriei tehnice și la deteriorarea treptată a experienței utilizatorului. Gestionarea corectă a erorilor non-fatal este una dintre abilitățile cheie ale dezvoltatorului mobil.
Principalele idei
Non-Fatal Error — este o excepție sau o stare eronată care nu provoacă terminarea procesului. Aplicația continuă să funcționeze, dar poate fi într-o stare incorectă: datele nu s-au încărcat, cererea nu s-a trimis, elementul de interfață nu s-a afișat. Utilizatorul fie nu observă eroarea, fie vede un mesaj și continuă utilizarea aplicației.
O eroare nefatală lasă întotdeauna programului o cale de recuperare. Gestionarul de erori poate oferi date alternative, reîncerca operația sau afișa un substituent de interfață. Sarcina principală este prevenirea crash-ului și menținerea experienței utilizatorului la un nivel acceptabil. Dezvoltatorul trebuie să prevadă în mod explicit un scenariu de recuperare în fiecare bloc catch.
Conform datelor Instabug 2024, 65% dintre utilizatori șterg aplicația după două interacțiuni eșuate. Erorile non-fatal lăsate fără atenție se acumulează și reduc calitatea generală a funcționării. Logarea și remedierea sistematică a erorilor nefatale este o cale directă de creștere a retenției și de îmbunătățire a evaluărilor utilizatorilor în magazinele de aplicații.
Erori de rețea — cel mai frecvent tip de erori non-fatal în aplicațiile mobile. Expirarea conexiunii, pierderea rețelei, cod de stare incorect al serverului — toate aceste situații sunt interceptate și gestionate fără crash. Utilizatorului i se afișează un mesaj despre indisponibilitatea serviciului cu propunerea de a reîncerca. Pentru erorile de rețea este tipic tiparul retry cu întârziere exponențială.
Format incorect al răspunsului serverului, lipsa unui câmp obligatoriu, tip de date incorect — erorile de parsare sunt nefatale dacă aplicația gestionează corect datele incorecte. Abordarea tipică este utilizarea valorilor implicite de rezervă și logarea erorii de parsare cu contextul cererii pentru analiza ulterioară pe server.
Probleme cu încărcarea imaginilor, fonturi incorecte, erori de layout — toate nu sunt fatale, dar înrăutățesc impresia utilizatorului. Imaginile placeholder și valorile fallback permit evitarea ecranelor goale și fac erorile mai puțin vizibile. În React Native pentru erorile UI se folosește Error Boundary cu afișarea unei componente de rezervă.
Erori în calcule, neconcordanță de stări, tranziții incorecte între ecrane — erorile logice adesea nu duc la crash, dar conduc la comportament incorect al aplicației. Sunt mai greu de depistat fără logare și monitorizare sistematică, deoarece nu creează rapoarte de crash și rămân neobservate până la reclamația utilizatorului.
Non-Fatal Error se deosebește de fatal prin faptul că lasă programului posibilitatea de a continua lucrul. Fatal error — este o stare din care aplicația nu se poate recupera: dereferențierea unui pointer null, depășirea stivei, insuficiență de memorie. Eroarea non-fatal poate fi interceptată, gestionată și execuția continuată, în timp ce fatal error necesită repornirea aplicației.
| Caracteristică | Non-Fatal Error | Fatal Error |
|---|---|---|
| Terminarea aplicației | Nu | Da |
| Posibilitate de recuperare | Da, prin bloc catch | Nu |
| Logare | Din cod prin recordException | Doar de raportorul de crash |
| Impact UX | Inconvenient temporar | Pierdere completă a sesiunii |
| Exemplu | Network timeout, parse error | NullPointerException, OOM |
Granita dintre non-fatal și fatal poate depinde de implementare. Timeout-ul de rețea într-o aplicație este gestionat ca non-fatal (reîncercarea cererii după 1–2 secunde), în alta poate fi fatal (crash în absența gestionarului). Gestionarea calitativă a erorilor transformă situațiile potențial fatale în nefatale, sporind stabilitatea aplicației. Proiectarea sistemului de gestionare a erorilor este una dintre sarcinile arhitecturale cheie la dezvoltarea unei aplicații mobile cu cerințe înalte de fiabilitate. Sistemul de monitorizare încorporat permite echipei să detecteze și să remedieze rapid erorile nefatale înainte ca acestea să afecteze un număr semnificativ de utilizatori.
Firebase Crashlytics — instrumentul principal pentru logarea erorilor nefatale în aplicațiile mobile. Metoda recordException permite înregistrarea unei excepții non-fatal cu stack trace complet și context de execuție, fără a întrerupe funcționarea aplicației. Spre deosebire de rapoartele de crash, recordException poate fi apelat în orice loc din cod pentru logarea excepțiilor interceptate.
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: folosim date de rezervă
Crashlytics.recordException(e)
showFallbackContent()
}
}
// Logare cu chei personalizate
Crashlytics.setCustomKey("screen", "Profile")
Crashlytics.setCustomKey("api_version", "v3")
Sentry — alternativă la Crashlytics cu diagnosticare mai detaliată a erorilor non-fatal. SDK-ul Sentry oferă metoda captureException, care trimite detaliile excepției pe server. Avantajul cheie al Sentry este gruparea erorilor non-fatal similare într-un singur issue, analiza frecvenței de repetare și contextul de execuție sub formă de breadcrumbs — secvența acțiunilor utilizatorului înainte de eroare.
Nu toate erorile non-fatal trebuie logate. Stările așteptate — lipsa rețelei în absența conexiunii — pot fi logate selectiv. Erorile neașteptate — NullPointerException în codul gestionat, format incorect al datelor, logic error — trebuie logate întotdeauna. Fiecare echipă determină pragul de semnificație: în medie între 10 și 20 de erori non-fatal unice la 1000 de utilizatori pe zi este considerat normal. Este important să se configureze alerte pentru creșterea bruscă a numărului de erori non-fatal — aceasta poate indica probleme cu noua versiune API sau regresie după lansare.
Mecanismul de bază de gestionare — try-catch, care interceptează excepția și execută codul de recuperare. Pentru operațiile de rețea, tiparul tipic este reîncercarea cererii cu întârziere exponențială (retry with backoff). Pentru erorile de parsare — utilizarea valorilor implicite de rezervă și logarea contextului pentru analiza ulterioară pe partea serverului.
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)
}
Tipuri Result — abordare alternativă fără excepții. Funcția returnează o sealed class Result cu variantele Success și Failure. Codul apelant gestionează ambele variante explicit, ceea ce elimină erorile negestionate. Tipurile Result sunt populare în Kotlin (Result
Pentru fiecare tip de eroare non-fatal trebuie prevăzută o strategie de recuperare: încărcarea datelor din cache la eroare de rețea, utilizarea valorilor implicite la eroare de parsare, reinițializarea componentei la eroare UI. O bună practică este afișarea unui toast sau snackbar cu mesajul de eroare, dar nu blocarea completă a interacțiunii cu aplicația. Este important să se facă distincția între erorile recuperabile (recoverable) și nerecuperabile — pentru cele din urmă strategia de recuperare va fi diferită, de exemplu, propunerea de a reporni ecranul sau de a șterge datele. Stocarea în cache a stării anterioare reușite se dovedește adesea cea mai simplă și mai eficientă modalitate de gestionare a erorilor non-fatal pe platformele mobile.
Întrebări frecvente
Warning — este un avertisment al compilatorului sau al analizorului static despre o problemă potențială în cod. Non-fatal error — este o excepție de runtime care a avut deja loc, dar nu a dus la crash. Warning poate fi eliminat înainte de compilare, non-fatal error — gestionat în timpul execuției printr-un bloc catch.
Nu, logarea excesivă aglomerează monitorizarea. Merită să fie logate erorile neașteptate în producție și ignorate stările așteptate: lipsa rețelei în absența conexiunii se loghează selectiv, iar NullPointerException în codul gestionat — întotdeauna. Fiecare echipă determină pragul de semnificație în funcție de contextul aplicației.
În SwiftUI se folosește ObservableObject cu un câmp @Published errorState pentru urmărirea stării de eroare. View-ul se abonează la modificări și afișează conținut alternativ. Înainte de iOS 17 se aplica Combine cu gestionari, începând cu iOS 17 — SwiftData și macro-uri @Observable pentru actualizarea reactivă a UI.
Da, dacă eroarea provoacă o reacție în lanț. Exemplu: o defecțiune nefatală la încărcarea imaginii poate duce la o stare incorectă a UI, care apoi provoacă crash la încercarea de afișare. Gestionarea calitativă a erorilor non-fatal la fiecare nivel previne escaladarea lor la nivel fatal.
În iOS, erorile non-fatal sunt gestionate prin do-catch cu throw, în Android — prin try-catch cu excepții. iOS folosește NSError cu domenii și coduri de eroare, Android — excepții Java/Kotlin. Crashlytics funcționează la fel pe ambele platforme prin recordException, oferind o interfață unitară pentru monitorizare.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și