Überblick und Zweck
Wenn Nutzer Fehler sehen, verdienen sie klare Rückmeldungen darüber, was passiert ist und wie es behoben werden kann. Rohe Backend-Fehlermeldungen müssen normalisiert werden, um:
- Rauschen zu entfernen: Redundante "Error:"-Präfixe und Leerraum bereinigen
- Lecks zu verhindern: Sicherstellen, dass sensible Implementierungsdetails niemals den Nutzer erreichen
- Fallbacks bereitzustellen: Sichere Meldungen anzeigen, wenn Fehler leer oder fehlerhaft sind
- Konsistenz sicherzustellen: Dieselbe Logik auf alle 11+ Frontend-Module anwenden
- Debugging zu verbessern: Vollständige Fehlerdetails in Phantom Wing protokollieren, während Nutzern sichere Zusammenfassungen gezeigt werden
Das Problem: Generische vs. aussagekräftige Fehler
Vor der Standardisierung verwendeten PayCal-Module ad-hoc Fehlerbehandlung:
// ❌ SCHLECHT: Gibt den rohen Fehler preis, dupliziert Logik
PC.showToast(error?.message || 'Import fehlgeschlagen.');
PW.error(`Import fehlgeschlagen: ${error.message}`);
Probleme mit diesem Ansatz:
- Nutzer sehen verwirrende Rohmeldungen wie "ECONNREFUSED: Verbindung verweigert"
- Jedes Modul implementiert seine eigene Fallback-Logik unabhängig
- Kein konsistentes Abschneiden von Leerraum oder Entfernen von Präfixen
- Leere Fehlermeldungen können in der UI als "undefined" erscheinen
Die Lösung: Standardisierter Fehler-Resolver
Alle PayCal-Frontend-Module verwenden jetzt eine einheitliche Resolver-Funktion, die Fehlermeldungen normalisiert:
// ✅ GUT: Normalisiert, konsistent, sicher
const resolveThrownMessage = (error, fallbackMessage) => {
const raw = typeof error?.message === 'string'
? error.message
: String(error || '');
const normalized = raw.replace(/^Error:\s*/i, '').trim();
return normalized !== '' ? normalized : fallbackMessage;
};
Verwendung:
// In Catch-Blöcken über Module hinweg
try {
await updateProfile(data);
} catch (error) {
const message = resolveThrownMessage(error, 'Profil konnte nicht aktualisiert werden.');
PC.showToast(message, 'error'); // Nutzer sieht aussagekräftiges Feedback
PW.error(message); // Für Debugging protokolliert
}
Implementierungsumfang
Stand April 2026 wurde dieses standardisierte Fehlerbehandlungsmuster auf 11 Frontend-Module mit etwa 40+ normalisierten Catch-Blöcken angewendet:
Authentifizierung und Einstellungen (7 Module)
html/js/auth-recovery/index.php(4 catches)html/js/signin/index.php(2 catches)html/js/signin/verification-reminder.js(2 catches)html/js/signin/verification-status-banner.js(1 catch)html/js/settings/index.php(8+ catches)
Core- und Datenmodule (4 Module)
html/js/core/network.js(3 catches)html/js/core/index.php(5 catches)html/js/core/billing.js(5 catches)html/js/earnings/index.php(4 catches)
Hochwertige Module (10+ Catch-Punkte):
html/js/organizations/index.php- Organisationsverwaltung, Zugriffsanfragen, Audit-Trails (19+ catches)html/js/sites/index.php- Site CRUD, Einnahmen, Wiederherstellung verwaister Arbeit (10+ catches)html/js/calendar/calendar.js- Day-Entry-Operationen, Copy/Paste/Löschen (2 catches)
Fehlerkategorien und Behandlungsmuster
Der Resolver wird konsistent über mehrere Fehlerkategorien angewendet:
1. Netzwerkanforderungsfehler
// Netzwerkmodul: HTTP-Fehler, Timeouts, Verbindungsprobleme
async function deleteResource(ep, id) {
try {
// ...fetch-Logik...
} catch (error) {
const resolved = resolveThrownMessage(error, 'Netzwerkfehler');
const msg = `[deleteResource] ${resolved}`;
PW.error(msg);
throw new Error(msg);
}
}
2. API-Antwortverarbeitung
// Billing/Settings: Server gab Fehlermeldung in der Nutzlast zurück
try {
const response = await fetch('/api/v1/billing/subscription');
const payload = await response.json();
if (!response.ok) {
throw new Error(payload?.message || 'Abrechnungsstatus konnte nicht geladen werden.');
}
} catch (error) {
const resolved = resolveThrownMessage(error, 'Abrechnungsstatus konnte nicht geladen werden.');
setScreenReaderStatus(resolved);
}
3. UI-Fehler bei Operationen
// Calendar/Organizations: Nutzerinitiierte Aktionen (Einfügen, Löschen, Aktualisieren)
button.addEventListener('click', async () => {
try {
await performAction();
PC.showToast('Erfolg!', 'save');
} catch (error) {
const message = resolveThrownMessage(error, 'Aktion fehlgeschlagen. Bitte erneut versuchen.');
PC.showToast(message, 'error');
}
});
4. Asynchrone Initialisierung
// Core-Module: Start- oder abhängige Initialisierungsfehler
try {
NavigationToggle.init();
} catch (err) {
const resolved = resolveThrownMessage(err, 'Navigation initialisierung fehlgeschlagen');
PW.warn(resolved); // Protokolliert, blockiert die Seite aber nicht
}
Sicherheitsaspekte
Die Normalisierung von Fehlermeldungen schützt Privatsphäre und Systemintegrität:
- Keine Datenbankdetails: Backend-Fehler wie "UNIQUE constraint failed on email" werden an der API-Grenze abgefangen und durch benutzerfreundliche Meldungen ersetzt
- Keine Dateipfade: Systemfehler, die Dateipfade oder Prozessdetails offenlegen, werden entfernt
- Kein Auth-Leak: Antworten auf Authentifizierungsfehler verraten nie, ob ein Konto existiert (nur zeitlich sichere generische Meldungen)
- Keine CORS-/Netzwerkdetails: Transportfehler werden auf generische "Verbindungsfehler"-Meldungen normalisiert
- Sichere Fallbacks: Alle Catcher haben explizite Fallback-Meldungen; "undefined" oder "null" werden nie angezeigt
Vorteile für die Nutzererfahrung
Diese Standardisierung gibt Nutzern klareres, sichereres und konsistenteres Feedback und erleichtert dem Team Support und Debugging.
- Meldungen sind verständlich, ohne Implementierungsdetails preiszugeben
- Fallback-Text bleibt sicher, wenn der Backend-Fehler fehlt oder fehlerhaft ist
- Logging bleibt fürs Debugging nützlich, ohne sensible Werte in die UI zu leaken
Debugging- und Support-Workflow
Der Support kann sich auf einen konsistenten Resolver-Pfad verlassen und bei Bedarf die vollständigen technischen Details in Phantom Wing prüfen.
- Nutzer sieht normalisierte Meldung
- Phantom Wing protokolliert den vollständigen Fehlerkontext privat
- Support kann die Fehlerklasse korrelieren, ohne die rohe Backend-Antwort offenzulegen
Testing und Qualitätssicherung
Die Normalisierungslogik wird durch fokussierte Modultests und Integrationsprüfungen über die wichtigsten Frontend-Flows abgedeckt.
Wartung und zukünftige Erweiterungen
Wenn PayCal weitere Module hinzufügt, sollte dasselbe Resolver-Muster wiederverwendet statt eigener Fehlerformatierung dupliziert werden.
- Neue Module sollten direkt den gemeinsamen Resolver aufrufen
- Modulspezifische Fallback-Meldungen sollten kurz und nutzerorientiert bleiben
- Jede Änderung am Resolver sollte regressionsgetestet werden über repräsentative Flows
Das hält das Verhalten vorhersagbar, wenn die Codebasis wächst, und verhindert eine zweite Generation modulspezifischer Fehlerbehandlung.
Zusammenfassung: Der PayCal-Fehlerbehandlungsstandard
PayCal hat die Fehlerbehandlung im Frontend standardisiert, damit Nutzer sichere, konsistente Meldungen erhalten, während Entwickler die Informationen bekommen, die sie zum Debuggen brauchen.
- Fehlermeldungen vor der Anzeige normalisieren
- Implementierungsdetails vor Nutzern verbergen
- Expliziten Fallback-Text für leere oder fehlerhafte Fehler verwenden
- Technische Details privat für Support und Debugging protokollieren