JavaScript Errors

La gestion des erreurs en JavaScript

Les problèmes surviennent : coupures réseau, entrées inattendues, changements d'API. Une bonne gestion des erreurs évite que ces défaillances ne deviennent des pannes et ne frustrent vos utilisateurs.

intermediate14 min readUpdated 15 sept. 2026
js
// api.js
class HttpError extends Error {
  constructor(status) {
    super(`Request failed with status ${status}`);
    this.name = "HttpError";
    this.status = status;
  }
}

try {
  const res = await fetch("/api/data");
  if (!res.ok) throw new HttpError(res.status);
  const data = await res.json();
} catch (error) {
  if (error instanceof HttpError) report(error.status);
  else console.error(error);
}
Type de base
Error
Déclencher avec
throw
Gérer avec
try / catch / finally
Étendre avec
class extends Error
Async
try/catch + rejected promises
Filet de sécurité
Global error handlers

Pratique

Try, catch et finally

Modifiez le nombre pour déclencher l'erreur et observez l'ordre des messages.

Try, catch et finally

Modifiez le nombre pour déclencher l'erreur et observez l'ordre des messages.

Pourquoi c'est important

Pourquoi la gestion des erreurs est cruciale

Échouer gracieusement

Une erreur gérée permet à l'application de continuer à fonctionner et affiche un message utile à l'utilisateur plutôt qu'un écran blanc.

Déboguer plus rapidement

Des erreurs bien définies incluent un message, un type et une trace de pile (stack trace), transformant un mystère en un correctif de cinq minutes.

Instaurer la confiance

Une récupération claire et des messages honnêtes donnent l'impression que l'application est solide, même quand le réseau ne l'est pas.

Le tableau complet

Trois questions pour chaque échec

Une bonne gestion des erreurs répond systématiquement aux trois mêmes questions : qu'est-ce qui a échoué, qui doit être informé et quelle est la suite.

Détection

Qu'est-ce qui a échoué

Déclenchez des erreurs précises et typées au point de défaillance plutôt que de laisser un état invalide se propager.

Récupération

Qui gère l'erreur

Capturez l'erreur là où vous pouvez faire quelque chose de concret, et laissez tout le reste remonter (bubble up).

Communication

Quelle est la suite

Indiquez à l'utilisateur ce qu'il peut faire, loguez les détails pour les développeurs et maintenez l'application active.

Aperçu de la gestion des erreurs

Les outils que vous utiliserez

Objets Error

message, name, stack et cause — la structure native d'un échec.

throw

Déclenchez vos propres erreurs dès qu'une règle est enfreinte.

try / catch

Enveloppez le code risqué et gérez l'échec sans faire planter l'application.

finally

Nettoyage qui s'exécute, que la tentative ait réussi ou échoué.

Erreurs personnalisées

Sous-classes de Error transportant des données spécifiques à votre domaine.

Erreurs asynchrones

Promises rejetées et utilisation de try/catch autour d'un await.

Un bref aperçu

L'évolution de la gestion des erreurs en JavaScript

  1. 1995

    Des erreurs sur les erreurs

    Les débuts de JavaScript exposent window.onerror comme unique filet de sécurité global.

    95
  2. 1999

    Arrivée de try / catch

    ES3 apporte la gestion structurée des exceptions au langage.

    99
  3. 2015

    Promises et rejections

    ES6 introduit les rejections de promises non gérées, une nouvelle classe d'échecs à gérer.

    15
  4. 2021

    error.cause

    Les erreurs peuvent désormais encapsuler la cause sous-jacente, préservant ainsi le contexte original.

    21
  5. Aujourd'hui

    Culture de l'erreur explicite

    L'outillage, les linters et les frameworks privilégient tous une gestion des erreurs explicite et typée.

    Aujourd'hui

Le guide complet

La gestion des erreurs en JavaScript: Tout ce que vous devez savoir

Pourquoi les erreurs sont inévitables

Tout programme finit par rencontrer une situation imprévue : un serveur renvoie une erreur 500, un utilisateur saisit des lettres dans un champ numérique, un fichier est manquant ou une API tierce change de structure. La gestion des erreurs ne consiste pas à empêcher chaque panne, mais à décider de ce qui se passe lorsqu’elle survient.

Des erreurs bien gérées permettent à une application de continuer à fonctionner, informent l’utilisateur de manière utile et fournissent aux développeurs les détails nécessaires. À l’inverse, des erreurs mal gérées produisent des écrans blancs, des pertes de données silencieuses et des rapports de bugs impossibles à reproduire.

L’objet Error

JavaScript possède un type Error intégré, et chaque erreur levée est généralement une instance de celui-ci.

// error.js
const error = new Error("Something broke");

error.message; // "Something broke"
error.name;    // "Error"
error.stack;   // the call stack at the point of creation
error.cause;   // an optional underlying error

Il existe plusieurs sous-classes intégrées pour les catégories courantes : TypeError, ReferenceError, RangeError, SyntaxError, URIError et EvalError. Elles diffèrent principalement par leur nom et les situations qui les génèrent, ce qui les rend utiles pour le débogage et pour adapter le comportement du code selon le type d’échec.

Lever des erreurs

Utilisez throw pour signaler qu’une règle a été enfreinte. Levez un objet Error, jamais une chaîne de caractères ou un nombre — seules les instances Error transportent un message, un nom et une trace de pile (stack trace).

// validate.js
function divide(a, b) {
  if (b === 0) {
    throw new Error("Cannot divide by zero");
  }
  return a / b;
}

Lever une erreur précocement, exactement au point où une hypothèse n’est plus vérifiée, empêche un état invalide de se propager plus profondément dans votre programme. Échouer bruyamment durant le développement est une fonctionnalité, pas une nuisance.

try, catch et finally

try exécute du code risqué. Si une erreur est levée, le contrôle passe à catch. finally s’exécute dans tous les cas, ce qui en fait l’endroit idéal pour le nettoyage.

// try.js
try {
  const data = JSON.parse(input);
  save(data);
} catch (error) {
  console.error("Invalid data:", error.message);
} finally {
  setLoading(false);
}

Le paramètre catch est la valeur levée. Le JavaScript moderne supporte également la liaison catch optionnelle (optional catch binding) lorsque vous n’en avez pas besoin : catch { ... }. À l’intérieur d’un bloc catch, vous pouvez inspecter l’erreur, l’enregistrer dans les logs, tenter de récupérer l’état ou la relancer si vous ne pouvez pas la gérer.

// rethrow.js
try {
  await loadProfile();
} catch (error) {
  log(error);
  throw error; // let a higher layer decide
}

Classes d’erreur personnalisées

Les erreurs génériques perdent de leur sens à mesure que votre application s’agrandit. Les classes personnalisées vous permettent d’ajouter du contexte et de gérer la logique en fonction du type d’échec.

// http-error.js
class HttpError extends Error {
  constructor(status, message) {
    super(message ?? `HTTP ${status}`);
    this.name = "HttpError";
    this.status = status;
  }
}

class ValidationError extends Error {
  constructor(field, message) {
    super(message);
    this.name = "ValidationError";
    this.field = field;
  }
}

Désormais, les appelants peuvent réagir avec précision :

// handle.js
try {
  await save(form);
} catch (error) {
  if (error instanceof ValidationError) {
    showFieldError(error.field, error.message);
  } else if (error instanceof HttpError && error.status === 401) {
    redirectToLogin();
  } else {
    showGenericError();
  }
}

C’est toute la différence entre « une erreur est survenue » et « le champ email est déjà utilisé ».

Envelopper les erreurs avec cause

Parfois, vous souhaitez ajouter du contexte sans perdre l’échec d’origine. L’option cause permet de préserver la chaîne.

// cause.js
try {
  await db.query(sql);
} catch (error) {
  throw new Error("Failed to load orders", { cause: error });
}

L’erreur externe contient le contexte compréhensible par l’utilisateur, tandis que error.cause conserve les détails d’origine pour les logs et le débogage.

Erreurs dans le code asynchrone

Le code asynchrone présente deux chemins d’échec supplémentaires. Avec async/await, try/catch fonctionne exactement comme pour le code synchrone.

// async.js
async function load() {
  try {
    const res = await fetch("/api/data");
    if (!res.ok) throw new HttpError(res.status);
    return await res.json();
  } catch (error) {
    console.error("Load failed:", error);
    throw error;
  }
}

Sans await, attachez un gestionnaire à la promesse :

// promise.js
fetch("/api/data")
  .then((res) => res.json())
  .catch((error) => console.error(error));

Une promesse rejetée sans gestionnaire devient un unhandled rejection. Dans les navigateurs, cela génère un avertissement ; dans Node.js, cela peut interrompre le processus. Gérez toujours les rejets, ne serait-ce que pour les journaliser et les relancer.

Filets de sécurité globaux

Même avec un code rigoureux, certains problèmes finiront par passer entre les mailles du filet. Les gestionnaires globaux capturent ce que vous avez manqué afin que l’application puisse le signaler au lieu de planter silencieusement.

// global.js
window.addEventListener("error", (event) => {
  reportToServer(event.error);
});

window.addEventListener("unhandledrejection", (event) => {
  reportToServer(event.reason);
});

Dans Node.js, les équivalents sont process.on("uncaughtException") et process.on("unhandledRejection"). Considérez-les comme des derniers recours pour le logging et l’arrêt progressif (graceful shutdown), et non comme un substitut à la gestion des erreurs là où elles surviennent.

Validez avant de lever une exception

Tous les problèmes ne sont pas exceptionnels. Les conditions prévisibles — une entrée vide, un champ optionnel manquant, une recherche sans résultat — sont mieux gérées par la validation que par des exceptions.

// guards.js
function formatName(user) {
  if (!user?.name) return "Anonymous";
  return user.name.trim();
}

Réservez les exceptions aux situations réellement inattendues ou irrécupérables. Les utiliser pour le flux de contrôle ordinaire rend le code plus lent et plus difficile à suivre.

Communiquer avec les utilisateurs

Un message d’erreur technique est destiné aux développeurs. Les utilisateurs, quant à eux, doivent savoir ce qui s’est produit et quelle action ils peuvent entreprendre.

  • Gardez des messages courts et humains : « Nous n’avons pas pu enregistrer vos modifications. Vérifiez votre connexion et réessayez. »
  • Évitez le jargon, les stack traces et les codes de statut bruts dans l’interface.
  • Proposez une étape suivante : réessayer, revenir en arrière, contacter le support ou continuer hors ligne.
  • Journalisez l’intégralité des détails — message, stack, contexte — afin que le support puisse mener l’enquête.

Bonnes pratiques

  • Levez des objets Error, jamais des chaînes de caractères.
  • Ne capturez les erreurs que là où vous pouvez les résoudre ou ajouter un contexte utile.
  • Utilisez des classes d’erreur personnalisées pour les échecs spécifiques à votre domaine.
  • Enveloppez les erreurs avec cause au lieu de supprimer l’originale.
  • Gérez systématiquement les rejets de promesses.
  • Ajoutez des gestionnaires globaux comme dernier filet de sécurité, et envoyez les logs vers un service dédié.
  • Validez les conditions attendues plutôt que de lever des erreurs.
  • Séparez les messages destinés aux utilisateurs des diagnostics destinés aux développeurs.
  • Écrivez des tests pour vos scénarios d’échec, et pas seulement pour le “happy path”.

Erreurs courantes

  • Ignorer les erreurs avec un bloc catch vide.
  • Lever des chaînes de caractères et perdre ainsi la trace de la pile (stack trace).
  • Capturer une erreur et retourner une valeur par défaut qui masque un bug réel.
  • Oublier de gérer les promesses rejetées.
  • Afficher des messages d’erreur bruts aux utilisateurs.
  • Utiliser des exceptions pour le flux de contrôle ordinaire.
  • Supposer que try/catch autour d’un exécuteur de promesse capture les erreurs asynchrones — ce n’est pas le cas.

Et après ?

Les erreurs sont le point de rencontre entre le code asynchrone, l’Fetch API et la réalité. Associez les patterns présentés ici au DOM pour afficher des états conviviaux, et n’hésitez pas à revoir les fondamentaux de JavaScript dès qu’un TypeError vous rappelle que undefined n’est pas une fonction.

Lancer des erreurs

Lancez toujours des objets Error. Ils contiennent une trace de pile et un message, contrairement aux chaînes de caractères.

À privilégier
if (!user) {
  throw new Error("User not found");
}
À éviter
if (!user) {
  throw "User not found";
}

Attendu vs Exceptionnel

Validez les conditions attendues ; réservez try/catch pour les événements imprévisibles.

À privilégier
if (!response.ok) {
  throw new Error(`HTTP ${response.status}`);
}
À éviter
try {
  JSON.parse(input);
} catch {
  // swallowing every error hides bugs
}

FAQ

Foire aux questions

Keep learning

Related topics from the roadmap.

$ commencer à apprendre

Prêt à apprendre Error Handling ?

Notre tutoriel interactif vous guide à travers Error Handling pas à pas — avec des quiz et du vrai code que vous pouvez exécuter dans le navigateur.