Regel
Umgang mit Fehler in auffangen Blöcken.
Leere catch Blöcke geräuschlos schlucken Fehler,
macht Fehlersuche erschwert.
Unterstützte Sprachen: Java, C, C++, PHP, JavaScript,
TypeScript, Go, PythonEinleitung
Leere Catch-Blöcke gehören zu den gefährlichsten Anti-Patterns im Produktionscode. Werden Ausnahmen abgefangen, aber nicht behandelt, verschwindet der Fehler spurlos. Die Anwendung läuft mit korruptem Zustand, ungültigen Daten oder fehlgeschlagenen Operationen weiter, die die Ausführung hätten stoppen sollen. Benutzer erleben stille Fehler, bei denen Funktionen nicht funktionieren, aber keine Fehlermeldungen erhalten. Operationsteams haben keine Logs zum Debuggen. Das einzige Anzeichen dafür, dass etwas nicht stimmt, zeigt sich Stunden oder Tage später, wenn kaskadierende Fehler das System unbrauchbar machen.
Warum es wichtig ist
Debugging und Incident Response: Leere Catch-Blöcke eliminieren Fehlerprotokolle. Ingenieure haben keinen Stack-Trace, keine Fehlermeldung und keinen Hinweis darauf, wann oder wo der Fehler aufgetreten ist, was die Reproduktion von Problemen nahezu unmöglich macht.
Stille Datenkorruption: Wenn Datenbankoperationen oder API-Aufrufe innerhalb leerer Catch-Blöcke fehlschlagen, fährt die Anwendung fort, als wären sie erfolgreich gewesen. Datensätze werden teilweise aktualisiert, Transaktionen sind unvollständig, und wenn die Korruption entdeckt wird, ist der Audit-Trail verschwunden.
Sicherheitslücken: Leere Catch-Blöcke maskieren Sicherheitsfehler wie Authentifizierungsfehler oder Autorisierungsprüfungen. Ein Angreifer, der eine Ausnahme in einem sicherheitskritischen Pfad auslöst, könnte Schutzmaßnahmen vollständig umgehen, wenn der Fehler stillschweigend verschluckt wird.
Kaskadierende Fehler: Wenn Fehler unterdrückt werden, läuft die Anwendung in einem ungültigen Zustand weiter. Nachfolgende Operationen, die vom Ergebnis der fehlgeschlagenen Operation abhängen, werden ebenfalls fehlschlagen, wodurch eine Fehlerkette entsteht, die Ingenieure von der eigentlichen Ursache ablenkt.
Code-Beispiele
❌ Nicht konform:
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 };
}Warum es falsch ist: Wenn eine Operation fehlschlägt, wird der Fehler stillschweigend ignoriert und die Funktion gibt Erfolg zurück. Die Datenbank könnte aktualisiert werden, aber die Cache-Invalidierung könnte fehlschlagen, wodurch veraltete Daten zurückbleiben. Oder die Aktualisierung des Suchindex schlägt fehl, wodurch der Benutzer nicht durchsuchbar ist, ohne dass ein Protokoll oder eine Warnung das Problem anzeigt.
✅ Konform:
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 }
);
}
}
Warum das wichtig ist: Jeder Fehler wird mit Kontext protokolliert und liefert Debugging-Informationen. Der Fehler wird an den Aufrufer weitergegeben, was eine ordnungsgemäße Fehlerbehandlung auf der entsprechenden Ebene ermöglicht. Überwachungssysteme können bei diesen Fehlern Alarm schlagen, und die Anwendung schlägt schnell fehl, anstatt mit einem ungültigen Zustand fortzufahren.
Fazit
Leere Catch-Blöcke sind in Produktionscode niemals akzeptabel. Jede abgefangene Ausnahme erfordert mindestens eine Protokollierung, und die meisten müssen an Aufrufer weitergegeben werden oder spezifische Wiederherstellungsaktionen auslösen. Wenn Sie einen Fehler tatsächlich ignorieren müssen, dokumentieren Sie den Grund dafür mit einem Kommentar, der die geschäftliche Begründung erläutert. Standardmäßig sollten Fehler immer explizit behandelt und nicht stillschweigend verworfen werden.
.avif)
