Learn / Rust Practical Systems
Error Modeling
Represent expected failures as types and keep surprising failures observable.
Course: Rust Practical Systems. Level: Intermediate. Topic: Systems reliability.
Stage: intermediate - Intermediate error modeling - Typed errors and HTTP response mapping. Represent expected failures as types and route unexpected failures into observable system signals.
Outcomes
- Separate user errors from system errors.
- Map domain errors to HTTP status codes.
- Log context without leaking secrets.
Concepts
- Result
- thiserror
- IntoResponse
- tracing
Concept flow
Show how typed errors and http response mapping moves from trigger to implementation outcome in Rust Systems.
- Domain error
- HTTP mapper
- Problem response
- Trace event
Session flow
- Model Result (concept, 8 min) — Name the decisions behind Result before writing code.
- Separate user errors from system errors.
- Explain where Result belongs in job orchestration service.
- Build the vertical slice (walkthrough, 15 min) — Implement the smallest useful slice in src/error.rs.
- Map domain errors to HTTP status codes.
- Connect thiserror to a working example.
- Verify and harden (exercise, 10 min) — Add structured logging for system failures.
- Log context without leaking secrets.
- Record one risk or follow-up before moving on.
Code example
Rust in src/error.rs.
#[derive(thiserror::Error, Debug)]
pub enum AppError {
#[error("record not found")]
NotFound,
#[error("database unavailable")]
Database(#[from] sqlx::Error),
}
impl IntoResponse for AppError {
fn into_response(self) -> Response {
match self {
AppError::NotFound => StatusCode::NOT_FOUND.into_response(),
AppError::Database(err) => {
tracing::error!(error = %err, "database failure");
StatusCode::INTERNAL_SERVER_ERROR.into_response()
}
}
}
}
Walkthrough examples
- Error Modeling in a job orchestration service — A team is extending an Axum service with a companion CLI and needs this lesson's pattern to be clear enough for review, testing, and future maintenance.
- File: src/error.rs
- File: tests/error-modeling.spec
- File: docs/rust-systems/error-modeling.md
- Start from the provided Rust snippet and make the intent visible in names and boundaries.
- Apply the checklist item "Name expected errors" before adding extra behavior.
- Write down how the implementation changes when thiserror fails or becomes slow.
Practice
- Create one domain error enum.
- Map it to HTTP responses.
- Add structured logging for system failures.
Checklist
- Name expected errors
- Map status codes
- Log system context
- Avoid leaking internals
Quiz prompts
- What should a service usually do with unexpected database errors? — Production services need observability for operators and safe responses for clients.
- A teammate wants to hide Result inside a convenient helper. What should you check first? — Place Result at the boundary that keeps job orchestration service behavior explicit, testable, and reviewable.
- Which artifact best proves this Rust Systems lesson is ready for review? — Production-ready learning needs evidence: a test, trace, command, screenshot, or log that catches the risk again.
- Intermediate error modeling: a teammate says the happy path works, but "Domain error enum" is still implicit. What should you ask for before merging? — Domain error enum belongs in the intermediate stage only when the decision is visible, testable, and tied to a realistic failure mode.
- A reviewer has five minutes to evaluate this intermediate Rust Systems slice. Which evidence is strongest? — Build an intermediate Rust error layer with typed domain errors, HTTP mapping, tracing for system failures, and response-shape tests.
Flashcards
- Intermediate error modeling: what decision does "Domain error enum" force you to make? Name expected application failures before they become stringly typed branches. Evidence prompt: Add one domain error enum with user-safe display text.
- Intermediate error modeling: what decision does "HTTP error mapper" force you to make? Map domain errors to status codes and problem responses without leaking internals. Evidence prompt: Map not-found, conflict, and validation-style errors to distinct responses.
- Intermediate error modeling: what decision does "Tracing system failures" force you to make? Log dependency and unexpected failures with context while keeping response bodies safe. Evidence prompt: Capture one tracing event for a database failure and verify the client response is sanitized.
- In Rust Systems, what should you remember about Result? Result matters here because it supports "Separate user errors from system errors.".
- In Rust Systems, what should you remember about thiserror? thiserror matters here because it supports "Map domain errors to HTTP status codes.".
- In Rust Systems, what should you remember about IntoResponse? IntoResponse matters here because it supports "Log context without leaking secrets.".
- In Rust Systems, what should you remember about tracing? tracing matters here because it supports "Separate user errors from system errors.".
Labs
- Ship a error modeling slice — Extend an Axum service with a companion CLI with a small but reviewable feature that proves the lesson's architecture in code.
- Build an intermediate Rust error layer with typed domain errors, HTTP mapping, tracing for system failures, and response-shape tests.
- Add one domain error enum with user-safe display text.
- Map not-found, conflict, and validation-style errors to distinct responses.
- Capture one tracing event for a database failure and verify the client response is sanitized.
- Create one domain error enum.
- Map it to HTTP responses.
- The lab demonstrates the intermediate error modeling outcome without skipping earlier contract evidence.
- Each subtopic has a concrete artifact: Domain error enum, HTTP error mapper, Tracing system failures.
- The review notes explain how this level changes ownership, verification, or operational risk.
Challenge
- Review-ready error modeling (Core) — Build an intermediate Rust error layer with typed domain errors, HTTP mapping, tracing for system failures, and response-shape tests.
- All checklist items are either implemented or documented with a reason.
- The change can be understood from src/error.rs plus one short note.
- The concept diagram names ownership, failure handling, and verification points.
- A teammate could run the verification steps without asking for hidden context.
Canonical lesson URL