modulo 02 / lezione 10

Leggere errori e stack trace

Anatomia di un messaggio di errore

Leggere tipo, messaggio, file, riga e contesto distinguendo Error, TypeError, RangeError, SyntaxError e usando name, message e cause.

50 min Debugging

In parole semplici

Un messaggio di errore non è una pagina di codice. È una scheda di pronto soccorso: tipo, sintomo, posizione, contesto. Saper leggere ogni campo separatamente trasforma una stringa spaventosa in una serie ordinata di indizi.

Parole nuove

  • classe di errore (Error class): tipo di errore (TypeError, RangeError, ecc.).
  • message: descrizione testuale del problema.
  • stack: pila delle chiamate al momento dell’errore.
  • cause: errore originario che ha provocato l’errore corrente.

Cosa impari

  • Distinguere le quattro classi più comuni in JavaScript.
  • Identificare le quattro parti di un messaggio: tipo, message, file:riga, contesto.
  • Usare Error.cause per concatenare errori senza perdere la causa originaria.

Quattro parti di ogni errore

Esempio:

TypeError: Cannot read properties of undefined (reading 'nome')
    at mostraUtente (app.js:42:18)
    at handleClick (app.js:60:5)
    at HTMLButtonElement.<anonymous> (app.js:75:3)

Le parti:

  1. Classe: TypeError.
  2. Message: Cannot read properties of undefined (reading 'nome').
  3. Stack trace: la pila di chiamate (vedremo nella prossima lezione).
  4. Contesto implicito: file app.js, riga 42, colonna 18.

Leggi sempre tutte e quattro le parti, mai una sola.

Le quattro classi più comuni in JavaScript

TypeError

Stai usando un valore in un modo incompatibile con il suo tipo.

const u = undefined;
u.nome;             // TypeError: Cannot read properties of undefined (reading 'nome')

null.toString();    // TypeError

const arr = [1, 2];
arr();              // TypeError: arr is not a function

Indica: il valore non era quello che ti aspettavi.

RangeError

Un valore è fuori dal dominio accettato.

new Array(-1);                  // RangeError: Invalid array length
(123).toString(37);             // RangeError: toString() radix must be between 2 and 36
function r() { return r(); }
r();                            // RangeError: Maximum call stack size exceeded

Indica: il valore è del tipo giusto, ma non in un intervallo accettabile.

SyntaxError

Il codice non è valido (parse-time, modulo 0).

SyntaxError: Unexpected token '{'

Spesso non ha stack trace utile, perché il programma non è mai partito.

ReferenceError

Stai usando un nome non definito.

console.log(qualcosa);  // ReferenceError: qualcosa is not defined

Indica: lo scope non contiene quel nome (oppure è scritto male).

Tabella delle quattro classi

ClasseSignificatoEsempio tipico
TypeErrortipo incompatibilenull.x, arr is not a function
RangeErrorvalore fuori rangearray negativo, ricorsione infinita
SyntaxErrorcodice non validoparentesi mancante
ReferenceErrornome non definitovariabile mai dichiarata

Altre classi che incontrerai: URIError, EvalError (raro), e classi custom (MyError extends Error).

name, message, cause

Ogni Error ha tre proprietà fondamentali:

const e = new Error("Lettura fallita");
e.name;     // "Error"
e.message;  // "Lettura fallita"
e.stack;    // "Error: Lettura fallita\n    at ..."

cause per concatenare

Quando un errore “alto” è provocato da un errore “basso”, cause (introdotto nel 2021) preserva la catena:

async function caricaUtente(id) {
  try {
    const r = await fetch(`/api/utenti/${id}`);
    if (!r.ok) throw new Error(`HTTP ${r.status}`);
    return await r.json();
  } catch (err) {
    throw new Error(`Caricamento utente ${id} fallito`, { cause: err });
  }
}

In log:

Error: Caricamento utente 42 fallito
    at ...
[cause]: TypeError: Failed to fetch
    at ...

Senza cause, l’errore “alto” nasconde quello basso. Con cause, hai entrambi.

Lab: dieci errori da decifrare

Per ognuno scrivi: classe, traduzione in italiano del message, prima domanda tecnica da farsi.

1) TypeError: Cannot read properties of undefined (reading 'map')
2) TypeError: arr.filter is not a function
3) ReferenceError: nomeUtente is not defined
4) RangeError: Maximum call stack size exceeded
5) SyntaxError: Unexpected end of JSON input
6) TypeError: Failed to fetch
7) ReferenceError: Cannot access 'x' before initialization
8) RangeError: Invalid time value
9) TypeError: Converting circular structure to JSON
10) Error: ENOENT: no such file or directory, open './config.json'

Esempio compilato:

1) TypeError. "Stai cercando .map su qualcosa che è undefined." Domanda: dove proviene questo "qualcosa" e perché non è un array?

Glossario degli errori frequenti

Tieni nel taccuino una tabella errore → traduzione → causa tipica che cresce nel tempo. Diventa la tua memoria operativa.

Errori frequenti del principiante

  • Leggere solo la prima parola (“TypeError”) e ignorare il message.
  • Copiare l’errore in Google senza tradurlo. Spesso la traduzione “letterale” già dice cosa cercare.
  • Confondere TypeError con SyntaxError. SyntaxError = codice rotto. TypeError = valore inatteso.
  • Ignorare cause. Mostra dove il problema è nato davvero.