Regla
Manejar errores en captura bloques.
Vacío catch vacíos en silencio se tragan errores,
haciendo depuración la depuración.
Lenguajes soportados: Java, C, C++, PHP, JavaScript,
TypeScript, Go, PythonIntroducción
Los bloques catch vacíos son uno de los anti-patrones más peligrosos en el código de producción. Cuando las excepciones se capturan pero no se manejan, el error desaparece sin dejar rastro. La aplicación continúa ejecutándose con estado corrupto, datos inválidos u operaciones fallidas que deberían haber detenido la ejecución. Los usuarios ven fallos silenciosos en los que las funciones no funcionan pero no reciben mensajes de error. Los equipos de operaciones no tienen registros con los que depurar. El único indicio de que algo va mal llega horas o días después, cuando los fallos en cascada inutilizan el sistema.
Por qué es importante
Depuración y respuesta a incidentes: Los bloques de captura vacíos eliminan los registros de errores. Los ingenieros no tienen ningún rastro de pila, mensaje de error o indicación de cuándo o dónde se produjo el fallo, lo que hace que los problemas sean casi imposibles de reproducir.
Corrupción silenciosa de datos: Cuando las operaciones de la base de datos o las llamadas a la API fallan dentro de bloques de captura vacíos, la aplicación continúa como si hubieran tenido éxito. Los registros se actualizan parcialmente, las transacciones quedan incompletas y, para cuando se descubre la corrupción, la pista de auditoría ha desaparecido.
Vulnerabilidades de seguridad: Los bloques de captura vacíos ocultan fallos de seguridad como errores de autenticación o comprobaciones de autorización. Un atacante que desencadene una excepción en una ruta crítica para la seguridad podría saltarse las protecciones por completo si se traga el error silenciosamente.
Fallos en cascada: Cuando se tragan los errores, la aplicación continúa en un estado no válido. Las operaciones posteriores que dependan del resultado de la operación fallida también fallarán, creando una cadena de fallos que despista a los ingenieros de la causa raíz real.
Ejemplos de códigos
❌ No 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 };
}Por qué es incorrecto: Si falla alguna operación, el error se ignora silenciosamente y la función devuelve éxito. La base de datos podría actualizarse pero la invalidación de la caché podría fallar, dejando datos obsoletos. O la actualización del índice de búsqueda falla, haciendo que el usuario no pueda buscar, sin ningún registro o alerta que indique el problema.
✅ Conforme:
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 }
);
}
}
Por qué es importante: Cada error se registra con contexto, proporcionando información de depuración. El error se propaga al autor de la llamada, lo que permite una gestión adecuada de los errores en el nivel apropiado. Los sistemas de supervisión pueden alertar sobre estos errores, y la aplicación falla rápidamente en lugar de continuar con un estado no válido.
Conclusión
Los bloques de captura vacíos nunca son aceptables en el código de producción. Todas las excepciones capturadas deben registrarse como mínimo, y la mayoría deben propagarse a quienes las llaman o desencadenar acciones de recuperación específicas. Si realmente necesitas ignorar un error, documenta por qué con un comentario que explique la justificación de negocio. Por defecto, los errores deben tratarse siempre de forma explícita, no descartarse silenciosamente.
.avif)
