Non-Fatal Error — é um erro que não encerra o aplicativo e permite continuar a execução do programa. Ao contrário de um fatal error, erros não fatais podem ser capturados, tratados e registrados sem perder a sessão do usuário. De acordo com a Documentação do Firebase Crashlytics, 2024, cerca de 70% de todos os erros registrados em aplicativos de produção são não fatais, mas ignorá-los leva ao acúmulo de dívida técnica e à degradação gradual da experiência do usuário. O tratamento correto de erros non-fatal é uma das principais habilidades do desenvolvedor móvel.
Pontos principais
Non-Fatal Error — é uma exceção ou estado de erro que não causa o encerramento do processo. O aplicativo continua funcionando, mas pode estar em um estado incorreto: dados não carregados, solicitação não enviada, elemento de interface não exibido. O usuário ou não percebe o erro, ou vê uma mensagem e continua usando o aplicativo.
Um erro não fatal sempre deixa um caminho de recuperação para o programa. O manipulador de erros pode fornecer dados alternativos, repetir a operação ou mostrar um placeholder de interface. O objetivo principal é evitar uma falha e manter uma experiência de usuário aceitável. O desenvolvedor deve prever explicitamente um cenário de recuperação em cada bloco catch.
De acordo com a Instabug 2024, 65% dos usuários desinstalam um aplicativo após duas interações malsucedidas. Erros não fatais deixados sem atenção se acumulam e degradam a qualidade geral. O registro e a correção sistemática de erros não fatais é um caminho direto para melhorar a retenção e as classificações nas lojas de aplicativos.
Erros de rede são o tipo mais comum de erros não fatais em aplicativos móveis. Tempo limite de conexão, perda de rede, código de status incorreto do servidor — todas essas situações são capturadas e tratadas sem falha. O usuário vê uma mensagem de indisponibilidade do serviço com opção de repetir. O padrão de repetição com backoff exponencial é típico para erros de rede.
Formato de resposta incorreto do servidor, campo obrigatório ausente, tipo de dado inválido — erros de análise são não fatais se o aplicativo tratar corretamente dados malformados. A abordagem típica é usar valores padrão de fallback e registrar o erro de análise com o contexto da solicitação para análise posterior no servidor.
Problemas de carregamento de imagens, fontes incorretas, erros de layout — todos são não fatais, mas degradam a experiência do usuário. Imagens placeholder e valores de fallback ajudam a evitar telas vazias e tornam os erros menos perceptíveis. Em React Native, usa-se Error Boundary para erros de UI com exibição de um componente alternativo.
Erros de cálculo, incompatibilidade de estado, transições incorretas entre telas — erros lógicos frequentemente não causam falha, mas levam a um comportamento incorreto do aplicativo. São mais difíceis de detectar sem registro e monitoramento sistemáticos, pois não geram um relatório de falha e permanecem despercebidos até uma reclamação do usuário.
Non-Fatal Error difere do fatal porque deixa ao programa a chance de continuar funcionando. Um fatal error é um estado do qual o aplicativo não pode se recuperar: desreferência de ponteiro nulo, estouro de pilha, falta de memória. Um erro não fatal pode ser capturado, tratado e a execução pode continuar, enquanto um fatal error requer reinicialização do aplicativo.
| Característica | Non-Fatal Error | Fatal Error |
|---|---|---|
| Encerramento do app | Não | Sim |
| Recuperação possível | Sim, via catch | Não |
| Registro | Do código via recordException | Apenas pelo relator de falhas |
| Impacto na UX | Inconveniência temporária | Falha completa da sessão |
| Exemplo | Timeout de rede, erro de análise | NullPointerException, OOM |
O limite entre non-fatal e fatal pode depender da implementação. Um timeout de rede em um aplicativo é tratado como não fatal (repetição após 1–2 segundos), enquanto em outro pode ser fatal (falha se não houver manipulador). O tratamento de erros de qualidade transforma situações potencialmente fatais em não fatais, aumentando a estabilidade do aplicativo. Projetar um sistema de tratamento de erros é uma das principais tarefas arquitetônicas ao desenvolver um aplicativo móvel com altos requisitos de confiabilidade. Um sistema de monitoramento integrado permite que a equipe detecte e corrija rapidamente erros não fatais antes que eles afetem um número significativo de usuários.
Firebase Crashlytics é a principal ferramenta para registrar erros não fatais em aplicativos móveis. O método recordException permite capturar uma exceção não fatal com stack trace completo e contexto de execução sem interromper o aplicativo. Ao contrário dos relatórios de falha, recordException pode ser chamado em qualquer lugar do código para registrar exceções capturadas.
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: usando dados de fallback
Crashlytics.recordException(e)
showFallbackContent()
}
}
// Registro com chaves personalizadas
Crashlytics.setCustomKey("screen", "Profile")
Crashlytics.setCustomKey("api_version", "v3")
Sentry é uma alternativa ao Crashlytics com diagnóstico mais detalhado para erros não fatais. O SDK do Sentry fornece o método captureException, que envia detalhes da exceção para o servidor. A principal vantagem do Sentry é agrupar erros não fatais semelhantes em um único issue, analisar a frequência de recorrência e fornecer contexto de execução como breadcrumbs — a sequência de ações do usuário antes do erro.
Nem todos os erros não fatais precisam ser registrados. Estados esperados — falha de rede quando não há conexão — podem ser registrados seletivamente. Erros inesperados — NullPointerException em código tratado, formato de dados inválido, erros lógicos — devem ser sempre registrados. Cada equipe define seu limite de importância: em média, 10 a 20 erros não fatais únicos por 1000 usuários por dia é considerado normal. É importante configurar alertas para um aumento brusco de erros não fatais — isso pode indicar problemas com uma nova versão da API ou regressão após um lançamento.
O mecanismo básico de tratamento é try-catch, que captura a exceção e executa código de recuperação. Para operações de rede, o padrão típico é repetição com backoff exponencial. Para erros de análise, a abordagem é usar valores padrão de fallback e registrar o contexto para análise posterior no servidor.
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)
}
Tipos Result — uma abordagem alternativa sem exceções. Uma função retorna uma classe selada Result com variantes Success e Failure. O código chamador trata ambas as variantes explicitamente, eliminando erros não tratados. Tipos Result são populares em Kotlin (Result
Para cada tipo de erro não fatal, deve-se planejar uma estratégia de recuperação: carregar dados em cache em um erro de rede, usar valores padrão em um erro de análise, reinicializar um componente em um erro de UI. Uma boa prática é mostrar ao usuário um toast ou snackbar com mensagem de erro sem bloquear completamente a interação com o aplicativo. É importante distinguir entre erros recuperáveis e não recuperáveis — para estes últimos, a estratégia de recuperação será diferente, como sugerir reiniciar a tela ou limpar dados. Armazenar em cache o estado bem-sucedido anterior é frequentemente a maneira mais simples e eficaz de lidar com erros não fatais em plataformas móveis.
Perguntas frequentes
Warning é um aviso do compilador ou analisador estático sobre um problema potencial no código. Um erro non-fatal é uma exceção em tempo de execução que já ocorreu, mas não causou falha. Um warning pode ser corrigido antes da compilação; um erro non-fatal deve ser tratado durante a execução por meio de um bloco catch.
Não, o registro excessivo polui o monitoramento. Erros inesperados em produção devem ser registrados, enquanto estados esperados devem ser ignorados: falha de rede quando offline pode ser registrada seletivamente, mas um NullPointerException em código tratado deve ser sempre registrado. Cada equipe define seu limite de importância com base no contexto do aplicativo.
Em SwiftUI, usa-se ObservableObject com um campo @Published errorState para rastrear o estado de erro. A view assina as alterações e exibe conteúdo alternativo. Antes do iOS 17, usava-se Combine com manipuladores; a partir do iOS 17, usam-se SwiftData e macros @Observable para atualizações reativas da UI.
Sim, se o erro desencadear uma reação em cadeia. Exemplo: uma falha não fatal no carregamento de imagem pode levar a um estado incorreto da UI, que então causa uma falha ao tentar exibir. O tratamento de qualidade de erros não fatais em cada nível impede sua escalada para o nível fatal.
No iOS, erros non-fatal são tratados via do-catch com throw; no Android, via try-catch com exceções. O iOS usa NSError com domínios e códigos de erro; o Android usa exceções Java/Kotlin. O Crashlytics funciona de forma idêntica em ambas as plataformas via recordException, fornecendo uma interface unificada de monitoramento.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também