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 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

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