Overzicht en doel
Wanneer gebruikers fouten tegenkomen, verdienen ze duidelijke feedback over wat er is gebeurd en hoe ze het kunnen oplossen. Ruwe backend-foutmeldingen moeten worden genormaliseerd om:
- Ruis te verwijderen: overbodige "Error:"-voorvoegsels en witruimte opschonen
- Lekken te voorkomen: gevoelige implementatiedetails bereiken nooit de gebruiker
- Fallbacks te bieden: veilige berichten tonen wanneer fouten leeg of ongeldig zijn
- Consistentie te waarborgen: dezelfde logica toepassen in alle 11+ frontendmodules
- Debugging te verbeteren: volledige foutdetails naar Phantom Wing loggen en gebruikers veilige samenvattingen tonen
Het probleem: generieke versus betekenisvolle fouten
Voor de standaardisatie gebruikten PayCal-modules ad-hoc foutafhandeling:
// ❌ BAD: Exposes raw error, duplicates logic
PC.showToast(error?.message || 'Import failed.');
PW.error(`Import failed: ${error.message}`);
Problemen met deze aanpak:
- Gebruikers zien verwarrende ruwe meldingen zoals "ECONNREFUSED: Connection refused"
- Elke module implementeert onafhankelijk eigen fallbacklogica
- Geen consistente trimming van witruimte of verwijdering van voorvoegsels
- Lege foutmeldingen kunnen als "undefined" in de UI verschijnen
De oplossing: gestandaardiseerde foutresolver
Alle PayCal-frontendmodules gebruiken nu een uniforme resolverfunctie die foutmeldingen normaliseert:
// ✅ GOOD: Normalized, consistent, safe
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;
};
Gebruik:
// In catch blocks across modules
try {
await updateProfile(data);
} catch (error) {
const message = resolveThrownMessage(error, 'Unable to update profile.');
PC.showToast(message, 'error'); // User sees meaningful feedback
PW.error(message); // Logged for debugging
}
Implementatiebereik
Vanaf april 2026 is dit gestandaardiseerde foutafhandelingspatroon toegepast op 11 frontendmodules met ongeveer 40+ genormaliseerde catch-blokken:
Authenticatie en instellingen (7 modules)
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- en datamodules (4 modules)
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)
Modules met hoge waarde (10+ catch-punten):
html/js/organizations/index.php- Org management, access requests, audit trails (19+ catches)html/js/sites/index.php- Site CRUD, earnings, orphan work recovery (10+ catches)html/js/calendar/calendar.js- Day-entry operations, copy/paste/delete (2 catches)
Foutcategorieen en afhandelingspatronen
De resolver wordt consistent toegepast in meerdere foutcategorieen:
1. Mislukte netwerkverzoeken
// Network module: HTTP errors, timeouts, connection issues
async function deleteResource(ep, id) {
try {
// ...fetch logic...
} catch (error) {
const resolved = resolveThrownMessage(error, 'Network error');
const msg = `[deleteResource] ${resolved}`;
PW.error(msg);
throw new Error(msg);
}
}
2. API-responsafhandeling
// Billing/Settings: Server returned error message in payload
try {
const response = await fetch('/api/v1/billing/subscription');
const payload = await response.json();
if (!response.ok) {
throw new Error(payload?.message || 'Unable to load billing status.');
}
} catch (error) {
const resolved = resolveThrownMessage(error, 'Unable to load billing status.');
setScreenReaderStatus(resolved);
}
3. UI-operatiefouten
// Calendar/Organizations: User-initiated actions (paste, delete, update)
button.addEventListener('click', async () => {
try {
await performAction();
PC.showToast('Success!', 'save');
} catch (error) {
const message = resolveThrownMessage(error, 'Action failed. Try again.');
PC.showToast(message, 'error');
}
});
4. Asynchrone initialisatie
// Core modules: Startup or dependent initialization failures
try {
NavigationToggle.init();
} catch (err) {
const resolved = resolveThrownMessage(err, 'Navigation init failed');
PW.warn(resolved); // Logged but doesn't block page
}
Beveiligingsoverwegingen
Normalisatie van foutmeldingen beschermt gebruikersprivacy en systeemintegriteit:
- Geen databasedetails: backendfouten zoals "UNIQUE constraint failed on email" worden aan de API-grens onderschept en vervangen door gebruikersvriendelijke berichten
- Geen bestandspaden: systeemfouten die bestandspaden of procesdetails tonen worden verwijderd
- Geen auth-lek: reacties op authenticatiefouten onthullen nooit of een account bestaat
- Geen CORS/netwerkdetails: transportfouten worden genormaliseerd naar generieke "Connection error"-berichten
- Veilige fallbacks: alle catchers hebben expliciete fallbackberichten; "undefined" of "null" wordt nooit getoond
Voordelen voor de gebruikerservaring
Deze standaardisatie geeft gebruikers duidelijkere, veiligere en consistentere feedback en maakt support en debugging eenvoudiger.
- Berichten zijn begrijpelijk zonder implementatiedetails te tonen
- Fallbacktekst blijft veilig wanneer de backendfout ontbreekt of ongeldig is
- Logging blijft nuttig voor debugging zonder gevoelige waarden naar de UI te lekken
Debugging- en supportworkflow
Support kan vertrouwen op een consistent resolverpad en daarna Phantom Wing-logs inspecteren voor volledige technische details.
- Gebruiker ziet een genormaliseerd bericht
- Phantom Wing legt de volledige foutcontext prive vast
- Support kan het probleemtype correleren zonder de ruwe backendrespons te tonen
Testing en kwaliteitsborging
De normalisatielogica wordt gedekt door gerichte moduletests en integratiechecks in de belangrijkste frontendflows.
Onderhoud en toekomstige uitbreidingen
Wanneer PayCal meer modules toevoegt, moet hetzelfde resolverpatroon worden hergebruikt in plaats van aangepaste foutformattering te dupliceren.
- Nieuwe modules moeten direct de gedeelde resolver aanroepen
- Modulespecifieke fallbackberichten moeten kort en gebruikersgericht blijven
- Wijzigingen aan de resolver moeten regressietests krijgen in representatieve flows
Zo blijft gedrag voorspelbaar terwijl de codebase groeit en ontstaat er geen tweede generatie modulespecifieke foutafhandeling.
Samenvatting: de PayCal-standaard voor foutafhandeling
PayCal heeft frontend-foutafhandeling gestandaardiseerd zodat gebruikers veilige, consistente berichten krijgen en ontwikkelaars de informatie behouden die ze nodig hebben voor debugging.
- Foutmeldingen normaliseren voor weergave
- Implementatiedetails verbergen voor gebruikers
- Expliciete fallbacktekst gebruiken voor lege of ongeldige fouten
- Technische details prive loggen voor support en debugging