rust 40 lines · 7 steps

How a custom error type maps to HTTP in Axum

A single AppError enum centralizes every failure mode and renders itself as a clean JSON HTTP response.

Explained by highlit
1use axum::{
2 http::StatusCode,
3 response::{IntoResponse, Response},
4 Json,
5};
6use serde_json::json;
7 
8#[derive(Debug, thiserror::Error)]
9pub enum AppError {
10 #[error("resource not found")]
11 NotFound,
12 #[error("invalid input: {0}")]
13 Validation(String),
14 #[error("unauthorized")]
15 Unauthorized,
16 #[error(transparent)]
17 Database(#[from] sqlx::Error),
18 #[error(transparent)]
19 Unexpected(#[from] anyhow::Error),
20}
21 
22impl IntoResponse for AppError {
23 fn into_response(self) -> Response {
24 let (status, message) = match self {
25 AppError::NotFound => (StatusCode::NOT_FOUND, self.to_string()),
26 AppError::Validation(_) => (StatusCode::UNPROCESSABLE_ENTITY, self.to_string()),
27 AppError::Unauthorized => (StatusCode::UNAUTHORIZED, self.to_string()),
28 AppError::Database(ref err) => {
29 tracing::error!(error = %err, "database failure");
30 (StatusCode::INTERNAL_SERVER_ERROR, "internal server error".to_owned())
31 }
32 AppError::Unexpected(ref err) => {
33 tracing::error!(error = %err, "unexpected failure");
34 (StatusCode::INTERNAL_SERVER_ERROR, "internal server error".to_owned())
35 }
36 };
37 
38 (status, Json(json!({ "error": message }))).into_response()
39 }
40}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Implementing IntoResponse lets one error type flow straight out of handlers and become a response automatically.
  2. 2Mapping each variant to a status code keeps HTTP semantics in one place instead of scattered across handlers.
  3. 3Logging internal errors while returning a generic message avoids leaking implementation details to clients.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How a custom error type maps to HTTP in Axum — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code