Log in·Sign up
BestRelay

Back to the Journal

Rust Errors Become Clear When Failures Stay Explicit

Rust makes failure part of your function’s promise

Rust error handling becomes easier when you stop treating failure as an interruption and start treating it as information. A function can return a value that explicitly describes success or failure, and its caller must decide what happens next. An AI tutor is useful here when it explains each decision before suggesting a shortcut.

Imagine a small application that reads a settings file and extracts a connection limit. The file might be missing, its contents might contain an invalid number, or the number might violate an application rule. We will follow those failures through the program, one decision at a time.

First distinguish missing values from failed operations

Begin with Option, which represents either a present value or its absence. Looking up an optional setting is a natural example. Absence alone does not explain a failure; it simply says that no value is available.

Result represents either success or an error. Reading a file usually belongs here because failure carries useful information, such as a permission problem. Ask your tutor to identify what the caller needs to know. If absence is expected and needs no explanation, Option often fits. If the caller needs a reason, Result usually fits better.

Next handle each outcome where decisions belong

Start by explicitly matching the possible outcomes. Rust checks that a match covers every case, making the decision visible. For the optional connection limit, absence might select a documented default. For a file permission error, the application might stop and explain that it cannot read its settings.

Keep these choices tied to product behavior. A default is appropriate only when it is valid for the application. Silently replacing every failed read with default settings can hide a deployment mistake. Have the tutor describe the consequence of each branch before simplifying the implementation.

Then propagate failures until a caller can act

Once explicit handling makes sense, introduce the question mark operator. On a successful Result, it extracts the value so execution continues. On an error, it returns early from the enclosing function, converting the error through the From trait when necessary.

This requires a compatible return type. The operator also works with Option in functions returning Option, where absence causes an early return. It does not automatically turn a missing value into an explanatory error. That conversion requires an explicit choice about what absence means.

In our example, a settings reader can propagate a read failure. The application’s entry point can then decide how to report it and which exit status to use. Propagation moves responsibility to a suitable caller; it does not resolve the failure.

Give errors enough context to guide recovery

A parsing failure becomes more useful when the message identifies the setting being parsed. Preserve the underlying cause while adding that context. Avoid flattening every error into an indistinguishable message if callers need to react differently.

A custom error enum can distinguish reading, parsing, and validation failures. Implementing Display supplies a readable description, while implementing the standard Error trait lets the type participate in Rust’s error ecosystem. Its source method can expose an underlying cause. Libraries often benefit from structured errors that callers can inspect; applications may favor convenient wrappers when they mainly report failures.

Reserve panics for broken assumptions and invariants

Unwrap and expect extract a successful or present value, but panic on an error or absence. An explanatory expect message improves diagnosis without making the operation recoverable. Ordinary bad input should normally follow an explicit error path. Panics are better suited to broken assumptions or invariants whose violation indicates a programming defect.

Use your AI tutor to challenge decisions

Ask the tutor to trace missing settings, malformed numbers, and invalid limits through your design, then test those behaviors. BestRelay publishes this walkthrough and provides a quality-first API relay that forwards each request to the named official model without substitution. It supports Claude Code, Codex, Gemini CLI, and any OpenAI SDK. Billing is pay-as-you-go using provider-reported token counts, with cache reads and writes priced separately; members earn referral commissions when invitees top up. Create a BestRelay account to explore these exercises with an AI tutor.

Want to try the models discussed here? Sign up