Panoramica e scopo
Quando gli utenti incontrano errori, meritano un feedback chiaro che spieghi cosa è successo e come risolverlo. I messaggi di errore grezzi del backend devono essere normalizzati per:
- Eliminare il rumore: rimuovere i prefissi "Error:" ridondanti e pulire gli spazi
- Prevenire fughe: assicurarsi che i dettagli di implementazione sensibili non raggiungano mai l’utente
- Fornire fallback: mostrare messaggi sicuri quando gli errori sono vuoti o malformati
- Garantire coerenza: applicare la stessa logica a tutti gli 11+ moduli frontend
- Migliorare il debug: registrare i dettagli completi in Phantom Wing mostrando agli utenti riepiloghi sicuri
Il problema: errori generici vs messaggi utili
Prima della standardizzazione, i moduli PayCal usavano una gestione errori ad hoc:
// ❌ SBAGLIATO: espone l’errore grezzo, duplica la logica
PC.showToast(error?.message || 'Importazione fallita.');
PW.error(`Importazione fallita: ${error.message}`);
Problemi di questo approccio:
- Gli utenti vedono messaggi grezzi confusi come "ECONNREFUSED: Connessione rifiutata"
- Ogni modulo implementa indipendentemente la propria logica di fallback
- Nessuna pulizia coerente degli spazi o rimozione dei prefissi
- Messaggi di errore vuoti possono apparire come "undefined" nell’interfaccia
La soluzione: resolver di errore standardizzato
Tutti i moduli frontend PayCal ora usano una funzione resolver unificata che normalizza i messaggi di errore:
// ✅ GIUSTO: normalizzato, coerente, sicuro
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;
};
Uso:
// Nei blocchi catch in tutti i moduli
try {
await updateProfile(data);
} catch (error) {
const message = resolveThrownMessage(error, 'Impossibile aggiornare il profilo.');
PC.showToast(message, 'error'); // L’utente vede un feedback utile
PW.error(message); // Registrato per il debug
}
Ambito di implementazione
Ad aprile 2026, questo pattern standardizzato di gestione errori è stato applicato a 11 moduli frontend con circa 40+ blocchi catch normalizzati:
Autenticazione e impostazioni (7 moduli)
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)
Moduli core e dati (4 moduli)
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)
Moduli ad alto valore (10+ punti di catch):
html/js/organizations/index.php- gestione organizzazioni, richieste di accesso, audit trail (19+ catches)html/js/sites/index.php- CRUD siti, earnings, recupero lavoro orfano (10+ catches)html/js/calendar/calendar.js- operazioni day-entry, copia/incolla/elimina (2 catches)
Categorie di errore e pattern di gestione
Il resolver è applicato in modo coerente a diverse categorie di errore:
1. Fallimenti delle richieste di rete
// Modulo rete: errori HTTP, timeout, problemi di connessione
async function deleteResource(ep, id) {
try {
// ...logica fetch...
} catch (error) {
const resolved = resolveThrownMessage(error, 'Errore di rete');
const msg = `[deleteResource] ${resolved}`;
PW.error(msg);
throw new Error(msg);
}
}
2. Gestione delle risposte API
// Fatturazione/Impostazioni: il server ha restituito un messaggio di errore nel payload
try {
const response = await fetch('/api/v1/billing/subscription');
const payload = await response.json();
if (!response.ok) {
throw new Error(payload?.message || 'Impossibile caricare lo stato di fatturazione.');
}
} catch (error) {
const resolved = resolveThrownMessage(error, 'Impossibile caricare lo stato di fatturazione.');
setScreenReaderStatus(resolved);
}
3. Fallimenti nelle operazioni UI
// Calendario/Organizzazioni: azioni avviate dall’utente (incolla, elimina, aggiorna)
button.addEventListener('click', async () => {
try {
await performAction();
PC.showToast('Successo!', 'save');
} catch (error) {
const message = resolveThrownMessage(error, 'Azione fallita. Riprova.');
PC.showToast(message, 'error');
}
});
4. Inizializzazione asincrona
// Moduli core: avvio o errori di inizializzazione dipendente
try {
NavigationToggle.init();
} catch (err) {
const resolved = resolveThrownMessage(err, 'Inizializzazione navigazione fallita');
PW.warn(resolved); // Registrato ma non blocca la pagina
}
Considerazioni di sicurezza
La normalizzazione dei messaggi di errore protegge la privacy dell’utente e l’integrità del sistema:
- Nessun dettaglio database: errori backend come "UNIQUE constraint failed on email" vengono intercettati al confine API e sostituiti con messaggi user-friendly
- Nessun percorso file: gli errori di sistema che espongono percorsi file o dettagli di processo vengono rimossi
- Nessuna fuga auth: le risposte ai fallimenti di autenticazione non rivelano mai se un account esiste (solo messaggi generici sicuri rispetto al timing)
- Nessun dettaglio CORS/rete: gli errori di trasporto vengono normalizzati in messaggi generici "Errore di connessione"
- Fallback sicuri: tutti i catcher hanno messaggi di fallback espliciti; mai "undefined" o "null"
Vantaggi per l’esperienza utente
Questa standardizzazione offre agli utenti feedback più chiaro, sicuro e coerente, rendendo più facili supporto e debug per il team.
- I messaggi sono comprensibili senza esporre dettagli di implementazione
- Il testo di fallback resta sicuro quando l’errore backend manca o è malformato
- La registrazione resta utile per il debug senza esporre valori sensibili nell’interfaccia
Workflow di debug e supporto
Il supporto può affidarsi a un percorso resolver coerente, poi ispezionare i log di Phantom Wing per il dettaglio tecnico completo quando necessario.
- L’utente vede un messaggio normalizzato
- Phantom Wing registra privatamente il contesto completo dell’errore
- Il supporto può correlare la classe di problema senza esporre la risposta grezza del backend
Test e quality assurance
La logica di normalizzazione è coperta da test di modulo mirati e da controlli di integrazione sui principali flussi frontend.
Manutenzione ed estensioni future
Man mano che PayCal aggiunge altri moduli, lo stesso pattern resolver dovrebbe essere riutilizzato invece di duplicare un formato di errore personalizzato.
- I nuovi moduli dovrebbero chiamare direttamente il resolver condiviso
- I messaggi di fallback specifici del modulo devono restare brevi e orientati all’utente
- Ogni modifica al resolver dovrebbe essere testata in regressione su flussi rappresentativi
Così il comportamento resta prevedibile mentre la codebase cresce e si evita una seconda generazione di gestione errori specifica per modulo.
Riepilogo: lo standard PayCal per la gestione degli errori
PayCal ha standardizzato la gestione degli errori frontend affinché gli utenti ottengano messaggi sicuri e coerenti mentre gli sviluppatori ricevano le informazioni necessarie per il debug.
- Normalizzare i messaggi di errore prima della visualizzazione
- Nascondere i dettagli di implementazione agli utenti
- Usare testo di fallback esplicito per errori vuoti o malformati
- Registrare privatamente i dettagli tecnici per supporto e debug