Un atelier Rust · Édition d'ApprentissageA Rust Workshop · Learning Edition

Concevoir ses erreurs : thiserror vs anyhow Designing your errors: thiserror vs anyhow

Un type d'erreur qui dit ce qui a échoué — et le choix bibliothèque vs application : enum d'erreur précis et From pour une lib, contexte agrégé pour une app. An error type that says what failed — and the library vs application choice: a precise error enum and From for a lib, aggregated context for an app.

AudienceAudience
Dev maîtrisant Result et l'opérateur ? (Vol 4 №1) Dev fluent in Result and the ? operator (Vol 4 №1)
Format
Self-paced
ChapitresChapters
5
Date
Juin 2026 Jun 2026
≈ 18 min ●●●○ Erreursthiserroranyhow

Chapitre 1 en accès libre — la suite (ch. 2 à 5) est réservée. Chapter 1 free to read — the rest (ch. 2–5) is members-only.

01CadrageFraming3 min

Un Err qui ne dit rien, c'est un None déguisé.An Err that says nothing is a None in disguise.

Le numéro précédent a donné le contenant — Result, et le ? pour le faire circuler. Mais le E est resté vague. Or le pouvoir de Result vient justement de ce que l'échec transporte une information : sans elle, on retombe au niveau d'Option, où il n'y a qu'un « ça n'a pas marché ». Une erreur utile dit trois choses : ce qui a échoué (la cause), avec quel contexte (le fichier, la ligne, l'identifiant), et de manière que l'appelant puisse soit réagir au cas près, soit l'afficher proprement. Concevoir ses erreurs, c'est dessiner ce type E — et le premier réflexe est d'en faire un enum, une variante par façon d'échouer.The previous issue gave the container — Result, and the ? to move it around. But the E stayed vague. Yet Result's power comes precisely from failure carrying information: without it, you fall back to Option's level, where there's only a 'it didn't work'. A useful error says three things: what failed (the cause), with what context (the file, the line, the id), and in a way that lets the caller either react case by case or display it cleanly. Designing your errors means drawing that E type — and the first reflex is to make it an enum, one variant per way to fail.

L'erreur comme enum — une variante par cause, l'appelant peut trierThe error as an enum — one variant per cause, the caller can sort
// Un type d'erreur qui DIT ce qui a échoué — une variante par cause
enum ChargementError {
    FichierAbsent(PathBuf),       // on sait QUEL fichier manquait
    TomlInvalide(toml::Error),    // on garde la cause d'origine
    PortManquant,                 // une condition métier nommée
}

// l'appelant peut réagir au cas près :
match charger_config() {
    Err(ChargementError::FichierAbsent(p)) => creer_defaut(&p),  // récupérable
    Err(e) => return Err(e),                                     // le reste remonte
    Ok(c)  => c,
}
Réagir, ou afficherReact, or display

Il y a deux choses qu'on veut faire d'une erreur, et elles tirent le design dans deux directions. Réagir : reprendre sur tel cas précis (recréer un fichier absent, retenter sur un timeout) — ça exige un type où chaque cause est distinguable, donc un enum qu'on peut match. Afficher : présenter un message clair, avec le contexte de ce qu'on tentait — ça exige surtout une bonne chaîne de causes, pas forcément des variantes typées. Tout le numéro tient dans cet arbitrage, qui culminera au n°2 de ce volume en « bibliothèque vs application ».There are two things you want to do with an error, and they pull the design in two directions. React: resume on a precise case (recreate a missing file, retry on a timeout) — that needs a type where each cause is distinguishable, hence an enum you can match. Display: present a clear message, with context of what you were attempting — that mostly needs a good cause chain, not necessarily typed variants. The whole issue lives in this trade-off, peaking in this issue's 'library vs application'.

Le réflexe du numéroThe issue's reflex

« Quelqu'un voudra-t-il réagir à tel échec précis, ou juste savoir que ça a raté ? » Si l'appelant doit pouvoir trier les causes, donne-lui un enum où chacune est une variante. S'il ne fera qu'afficher, un type d'erreur agrégé, riche en contexte, suffit. La forme du type d'erreur découle de ce que son consommateur en fera.'Will someone want to react to this precise failure, or just know it failed?' If the caller must sort the causes, give them an enum where each is a variant. If they'll only display it, an aggregated, context-rich error type is enough. The error type's shape follows from what its consumer will do with it.

String n'est pas un type d'erreur.String is not an error type.

Renvoyer Err(format!("fichier absent…")) compile et semble pratique. Mais l'appelant ne reçoit qu'une phrase : il ne peut pas distinguer « fichier absent » de « port manquant » sans parser du texte. Une erreur en String, c'est jeter l'information au moment même où on la produit — l'enum la garde structurée jusqu'au point où quelqu'un décidera quoi en faire.Returning Err(format!("missing file…")) compiles and feels handy. But the caller gets only a sentence: they can't tell 'missing file' from 'missing port' without parsing text. A String error throws the information away at the very moment you produce it — the enum keeps it structured up to the point where someone decides what to do with it.

🔒

La suite est réservée The rest is members-only

Le premier numéro est libre. Débloque tout The Rust Loop — tous les volumes, à vie — pour 5 €, paiement unique. The first issue is free. Unlock all of The Rust Loop — every volume, forever — for €5, one-time.

Retour au kiosqueBack to newsstand