Non-Fatal Error у мобільних додатках — суть, види та обробка помилок

Автор: IT Sectr Опубліковано: 2026-05-27 Час читання: 8 хв

Non-Fatal Error — це помилка, яка не призводить до завершення роботи додатку і дозволяє продовжити виконання програми. На відміну від fatal error, нефатальні помилки можуть бути перехоплені, оброблені та залоговані без втрати сеансу користувача. За даними Firebase Crashlytics Documentation, 2024, близько 70% всіх зареєстрованих помилок у production-додатках є нефатальними, але їх ігнорування веде до накопичення технічного боргу та поступового погіршення користувацького досвіду. Коректна обробка non-fatal помилок — одна з ключових навичок мобільного розробника.

Головне

  • Non-Fatal Error — помилка, яка не завершує додаток і допускає відновлення виконання
  • Обробка нефатальних помилок включає try-catch, логування та відображення fallback UI
  • Логування non-fatal помилок критично важливе для пошуку прихованих багів у production
  • Fatal Error — протилежність: помилка, що викликає crash додатку без можливості відновлення
  • Crashlytics та Sentry дозволяють відстежувати non-fatal помилки в реальному часі

Що таке Non-Fatal Error

Non-Fatal Error — це виняток або помилковий стан, який не викликає завершення процесу. Додаток продовжує працювати, але може знаходитися в некоректному стані: не завантажилися дані, не відправився запит, не відобразився елемент інтерфейсу. Користувач або не помічає помилку, або бачить повідомлення та продовжує використання додатку.

Ключові ознаки

Нефатальна помилка завжди залишає програмі шлях для відновлення. Обробник помилок може запропонувати альтернативні дані, повторити операцію або показати заглушку інтерфейсу. Основне завдання — не допустити crash та зберегти користувацький досвід на прийнятному рівні. Розробник повинен явно передбачити сценарій відновлення в кожному catch-блоці.

Роль у стабільності додатків

За даними Instabug 2024, 65% користувачів видаляють додаток після двох невдалих взаємодій. Non-fatal помилки, залишені без уваги, накопичуються та знижують загальну якість роботи. Систематичне логування та виправлення нефатальних помилок — прямий шлях до підвищення retention та покращення користувацьких оцінок у магазинах додатків.

Види нефатальних помилок

Мережеві помилки — найпоширеніший тип non-fatal помилок у мобільних додатках. Таймаут з'єднання, втрата мережі, невірний статус-код сервера — всі ці ситуації перехоплюються та обробляються без crash. Користувачеві показується повідомлення про недоступність сервісу з пропозицією повторити спробу. Для мережевих помилок типовий патерн retry з експоненційною затримкою.

Помилки валідації даних

Невірний формат відповіді від сервера, відсутність обов'язкового поля, некоректний тип даних — помилки парсингу є нефатальними, якщо додаток коректно обробляє некоректні дані. Типовий підхід — використання запасних значень за замовчуванням та логування помилки парсингу з контекстом запиту для подальшого аналізу на сервері.

Помилки UI-рендерингу

Проблеми із завантаженням зображень, некоректні шрифти, помилки в layout — всі вони не фатальні, але погіршують враження користувача. Placeholder-зображення та fallback-значення дозволяють уникнути порожніх екранів і роблять помилки менш помітними. У React Native для UI-помилок використовують Error Boundary з відображенням запасного компонента.

Помилки бізнес-логіки та стану

Помилки в розрахунках, невідповідність станів, неправильні переходи між екранами — логічні помилки часто не призводять до crash, але призводять до некоректної поведінки додатку. Їх складніше виявити без систематичного логування та моніторингу, оскільки вони не створюють crash-репорт і залишаються непоміченими до скарги користувача.

Non-Fatal Error vs Fatal Error: порівняння

Non-Fatal Error відрізняється від fatal тим, що залишає програмі можливість продовжувати роботу. Fatal error — це стан, з якого додаток не може відновитися: розіменування null-покажчика, переповнення стеку, нестача пам'яті. Non-fatal помилку можна перехопити, обробити та продовжити виконання, в той час як fatal error вимагає перезапуску додатку.

ХарактеристикаNon-Fatal ErrorFatal Error
Завершення додаткуНіТак
Можливість відновленняТак, через catch-блокНі
ЛогуванняЗ коду через recordExceptionТільки crash-репортером
UX-впливТимчасове незручністьПовний збій сеансу
ПрикладNetwork timeout, parse errorNullPointerException, OOM

Межа між non-fatal та fatal може залежати від реалізації. Мережевий таймаут в одному додатку обробляється як non-fatal (повтор запиту через 1–2 секунди), в іншому може бути фатальним (crash за відсутності обробника). Якісна обробка помилок перетворює потенційно фатальні ситуації в нефатальні, підвищуючи стабільність додатку. Проектування системи обробки помилок — одне з ключових архітектурних завдань при розробці мобільного додатку з високими вимогами до надійності. Вбудована система моніторингу дозволяє команді швидко виявляти та усувати нефатальні помилки до того, як вони вплинуть на значну кількість користувачів.

Логування non-fatal помилок

Firebase Crashlytics — основний інструмент для логування нефатальних помилок у мобільних додатках. Метод recordException дозволяє зафіксувати non-fatal виняток з повним стектрейсом та контекстом виконання, не перериваючи роботу додатку. На відміну від crash-репортів, recordException можна викликати в будь-якому місці коду для логування перехоплених винятків.

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: використовуємо запасні дані
        Crashlytics.recordException(e)
        showFallbackContent()
    }
}

// Логування з користувацькими ключами
Crashlytics.setCustomKey("screen", "Profile")
Crashlytics.setCustomKey("api_version", "v3")

Sentry — альтернатива Crashlytics з більш детальною діагностикою non-fatal помилок. Sentry SDK надає метод captureException, який відправляє деталі винятку на сервер. Ключова перевага Sentry — групування схожих non-fatal помилок в один issue, аналіз частоти повторення та контекст виконання у вигляді breadcrumbs — послідовності дій користувача перед помилкою.

Критерії логування non-fatal помилок

Не всі non-fatal помилки потрібно логувати. Очікувані стани — відмова мережі за відсутності з'єднання — можна логувати вибірково. Неочікувані помилки — NullPointerException в обробленому коді, невірний формат даних, logic error — повинні логуватися завжди. Кожна команда визначає поріг значущості: в середньому від 10 до 20 унікальних non-fatal помилок на 1000 користувачів на день вважається нормою. Важливо налаштувати алерти на різке зростання числа non-fatal помилок — це може вказувати на проблеми з новою версією API або регресію після релізу.

Обробка non-fatal помилок у коді

Базовий механізм обробки — try-catch, який перехоплює виняток та виконує код відновлення. Для мережевих операцій типовий патерн — повтор запиту з експоненційною затримкою (retry with backoff). Для помилок парсингу — використання запасних значень за замовчуванням та логування контексту для подальшого аналізу на серверній стороні.

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)
}

Result-типи — альтернативний підхід без винятків. Функція повертає sealed class Result з варіантами Success та Failure. Викликаючий код обробляє обидва варіанти явно, що виключає необроблені помилки. Result-типи популярні в Kotlin (Result в стандартній бібліотеці) та Swift (Result) для явної обробки non-fatal станів на рівні типів.

Fallback-стратегії для non-fatal помилок

Для кожного типу non-fatal помилки потрібно передбачити стратегію відновлення: завантаження кешованих даних при мережевій помилці, використання значень за замовчуванням при помилці парсингу, повторна ініціалізація компонента при UI-помилці. Хороша практика — показувати користувачеві toast або snackbar з повідомленням про помилку, але не блокувати взаємодію з додатком повністю. Важливо розрізняти recoverable (відновлювані) та non-recoverable помилки — для других стратегія відновлення буде іншою, наприклад, пропозиція перезапустити екран або очистити дані. Кешування попереднього успішного стану часто виявляється найпростішим і найбільш ефективним способом обробки non-fatal помилок на мобільних платформах.

Поширені запитання

Чим non-fatal помилка відрізняється від warning?

Warning — це попередження компілятора або статичного аналізатора про потенційну проблему в коді. Non-fatal error — це runtime-виняток, який вже стався, але не призвів до crash. Warning можна усунути до компіляції, non-fatal error — обробити під час виконання через catch-блок.

Чи потрібно логувати всі non-fatal помилки?

Ні, надмірне логування зашумлює моніторинг. Варто логувати неочікувані помилки в production та ігнорувати очікувані стани: відмова мережі при відсутності з'єднання логується вибірково, а NullPointerException в обробленому коді — завжди. Кожна команда визначає поріг значущості виходячи з контексту додатку.

Як обробити non-fatal помилку в SwiftUI?

У SwiftUI використовується ObservableObject з @Published полем errorState для відстеження помилкового стану. View підписується на зміни та відображає альтернативний контент. До iOS 17 застосовувався Combine з обробниками, починаючи з iOS 17 — SwiftData та @Observable макроси для реактивного оновлення UI.

Чи може non-fatal помилка стати fatal?

Так, якщо помилка викликає ланцюгову реакцію. Приклад: нефатальний збій завантаження зображення може призвести до некоректного стану UI, який потім викликає crash при спробі відображення. Якісна обробка non-fatal помилок на кожному рівні запобігає їх ескалації до фатального рівня.

Як відрізняється non-fatal у iOS та Android?

В iOS non-fatal помилки обробляються через do-catch з throw, в Android — через try-catch з винятками. iOS використовує NSError з доменами та кодами помилок, Android — Java/Kotlin винятки. Crashlytics працює однаково на обох платформах через recordException, надаючи єдиний інтерфейс для моніторингу.

Підсумки

  • Non-Fatal Error — runtime-помилка, що не завершує додаток та допускає відновлення виконання
  • Мережеві помилки, помилки парсингу та UI-рендерингу — три основних класи нефатальних помилок
  • Fatal Error — протилежність non-fatal, що викликає повний crash додатку без відновлення
  • Crashlytics та Sentry — основні інструменти логування non-fatal помилок у production
  • Result-типи — альтернатива виняткам для явної обробки помилкових станів на рівні типів
  • Placeholder-значення та fallback-стратегії запобігають видимому погіршенню користувацького досвіду
  • Систематичне виправлення non-fatal помилок підвищує retention та якість додатку згідно з Instabug

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також