Regra
Manusear erros em catch blocos.
Vazio catch vazios silenciosamente engolir erros,
tornando a depuração difícil.
Linguagens suportadas: Java, C, C++, PHP, JavaScript,
TypeScript, Go, PythonIntrodução
Os blocos de captura vazios são um dos antipadrões mais perigosos no código de produção. Quando as excepções são capturadas mas não tratadas, o erro desaparece sem deixar rasto. A aplicação continua a funcionar com o estado corrompido, dados inválidos ou operações falhadas que deveriam ter parado a execução. Os utilizadores vêem falhas silenciosas em que as funcionalidades não funcionam, mas não recebem mensagens de erro. As equipas de operações não têm registos para depurar. A única indicação de que algo está errado surge horas ou dias depois, quando as falhas em cascata tornam o sistema inutilizável.
Porque é importante
Depuração e resposta a incidentes: Os blocos de captura vazios eliminam os registos de erros. Os engenheiros não têm rastreamento de pilha, mensagem de erro ou indicação de quando ou onde a falha ocorreu, tornando os problemas quase impossíveis de reproduzir.
Corrupção silenciosa de dados: Quando as operações de base de dados ou chamadas de API falham dentro de blocos de captura vazios, a aplicação continua como se tivessem sido bem sucedidas. Os registos são parcialmente actualizados, as transacções ficam incompletas e, quando a corrupção é descoberta, a pista de auditoria já desapareceu.
Vulnerabilidades de segurança: Os blocos de captura vazios mascaram as falhas de segurança, como erros de autenticação ou verificações de autorização. Um atacante que desencadeie uma exceção num caminho crítico para a segurança pode contornar completamente as protecções se o erro for silenciosamente engolido.
Falhas em cascata: Quando os erros são engolidos, a aplicação continua num estado inválido. As operações subsequentes que dependem do resultado da operação falhada também falharão, criando uma cadeia de falhas que desvia os engenheiros da verdadeira causa principal.
Exemplos de código
Não conforme:
async function updateUserProfile(userId, profileData) {
try {
await db.users.update(userId, profileData);
await cache.invalidate(`user:${userId}`);
await searchIndex.update(userId, profileData);
} catch (error) {
// TODO: handle error
}
return { success: true };
}Porque é que está errado: Se alguma operação falhar, o erro é silenciosamente ignorado e a função devolve o sucesso. A base de dados pode ser actualizada, mas a invalidação da cache pode falhar, deixando os dados obsoletos. Ou a atualização do índice de pesquisa falha, tornando o utilizador indecifrável, sem qualquer registo ou alerta que indique o problema.
Conformidade:
async function updateUserProfile(userId, profileData) {
try {
await db.users.update(userId, profileData);
await cache.invalidate(`user:${userId}`);
await searchIndex.update(userId, profileData);
return { success: true };
} catch (error) {
logger.error('Failed to update user profile', {
userId,
error: error.message,
stack: error.stack
});
throw new ProfileUpdateError(
'Unable to update profile',
{ cause: error }
);
}
}
Porque é que isto é importante: Todos os erros são registados com contexto, fornecendo informações de depuração. O erro se propaga para o chamador, permitindo o tratamento adequado de erros no nível apropriado. Os sistemas de monitorização podem alertar sobre estes erros e a aplicação falha rapidamente em vez de continuar com um estado inválido.
Conclusão
Blocos catch vazios nunca são aceitáveis em código de produção. Todas as excepções capturadas precisam de ser registadas, no mínimo, e a maioria precisa de se propagar a quem as chama ou de desencadear acções de recuperação específicas. Se for realmente necessário ignorar um erro, documente o motivo com um comentário que explique a justificação comercial. O padrão deve ser sempre tratar os erros explicitamente, e não descartá-los silenciosamente.
.avif)
