pub struct ApiError {
pub code: String,
pub message: String,
pub details: Option<Value>,
}Expand description
A machine-readable JSON error body.
Serializes as:
{ "code": "NOT_FOUND", "message": "item not found" }
{ "code": "VALIDATION_ERROR", "message": "invalid input", "details": { "field": "name" } }Use the factory methods to get a (StatusCode, Json<ApiError>) tuple, which implements
[IntoResponse] and can be returned directly from Axum handlers.
§Example
use axum::response::IntoResponse;
use axum_api_kit::ApiError;
async fn handler() -> impl IntoResponse {
ApiError::not_found("item not found")
}Fields§
§code: StringA short, stable, machine-readable error identifier. Use SCREAMING_SNAKE_CASE.
message: StringA human-readable description of the error.
details: Option<Value>Optional structured details (field-level validation errors, etc.).
Implementations§
Source§impl ApiError
impl ApiError
Sourcepub fn new(code: impl Into<String>, message: impl Into<String>) -> Self
pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self
Construct a bare ApiError without a bundled status code.
Prefer the factory methods (not_found, etc.) when returning
responses directly from handlers.
Sourcepub fn with_details(self, details: Value) -> Self
pub fn with_details(self, details: Value) -> Self
Attach structured details to this error.
Sourcepub fn bad_request(
code: impl Into<String>,
message: impl Into<String>,
) -> (StatusCode, Json<Self>)
pub fn bad_request( code: impl Into<String>, message: impl Into<String>, ) -> (StatusCode, Json<Self>)
400 Bad Request with the provided code and message.
401 Unauthorized - code defaults to "AUTH_REQUIRED".
Sourcepub fn forbidden(message: impl Into<String>) -> (StatusCode, Json<Self>)
pub fn forbidden(message: impl Into<String>) -> (StatusCode, Json<Self>)
403 Forbidden - code defaults to "FORBIDDEN".
Sourcepub fn not_found(message: impl Into<String>) -> (StatusCode, Json<Self>)
pub fn not_found(message: impl Into<String>) -> (StatusCode, Json<Self>)
404 Not Found - code defaults to "NOT_FOUND".
Sourcepub fn conflict(message: impl Into<String>) -> (StatusCode, Json<Self>)
pub fn conflict(message: impl Into<String>) -> (StatusCode, Json<Self>)
409 Conflict - code defaults to "CONFLICT".
Sourcepub fn unprocessable(message: impl Into<String>) -> (StatusCode, Json<Self>)
pub fn unprocessable(message: impl Into<String>) -> (StatusCode, Json<Self>)
422 Unprocessable Entity - code defaults to "VALIDATION_ERROR".
Sourcepub fn internal(message: impl Into<String>) -> (StatusCode, Json<Self>)
pub fn internal(message: impl Into<String>) -> (StatusCode, Json<Self>)
500 Internal Server Error - code defaults to "INTERNAL_ERROR".
Sourcepub fn db_error() -> (StatusCode, Json<Self>)
pub fn db_error() -> (StatusCode, Json<Self>)
500 Internal Server Error for database failures - code is "DB_ERROR".
Sourcepub fn too_many_requests(message: impl Into<String>) -> (StatusCode, Json<Self>)
pub fn too_many_requests(message: impl Into<String>) -> (StatusCode, Json<Self>)
429 Too Many Requests - code defaults to "RATE_LIMITED".
503 Service Unavailable - code defaults to "SERVICE_UNAVAILABLE".
Sourcepub fn not_implemented(message: impl Into<String>) -> (StatusCode, Json<Self>)
pub fn not_implemented(message: impl Into<String>) -> (StatusCode, Json<Self>)
501 Not Implemented - code defaults to "NOT_IMPLEMENTED".
Sourcepub fn with_source(self, source: &str) -> Self
pub fn with_source(self, source: &str) -> Self
Attach a source error message to this error.
Stores the source in the details field under the "source" key.
Can be chained with other builder methods.
§Example
use axum_api_kit::ApiError;
let err = ApiError::new("NOT_FOUND", "user not found")
.with_source("SELECT * FROM users WHERE id = ?")
.with_details(serde_json::json!({ "user_id": 42 }));Trait Implementations§
Source§impl Error for ApiError
impl Error for ApiError
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<Error> for ApiError
Convert std::io::Error to ApiError with HTTP 500.
impl From<Error> for ApiError
Convert std::io::Error to ApiError with HTTP 500.
Maps std::io::Error to ApiError::internal() with the error message.
Enables using the ? operator in handlers:
async fn handler() -> impl IntoResponse {
let content = std::fs::read_to_string("/data.txt")?; // auto-converts to ApiError
Ok((StatusCode::OK, content))
}Source§impl From<Error> for ApiError
Convert serde_json::Error to ApiError with HTTP 500.
impl From<Error> for ApiError
Convert serde_json::Error to ApiError with HTTP 500.
Maps JSON errors to ApiError::internal() with the error message.
Source§impl From<Error> for ApiError
Available on crate feature sqlx only.Convert sqlx::Error to an ApiError with a semantically appropriate HTTP status.
impl From<Error> for ApiError
sqlx only.Convert sqlx::Error to an ApiError with a semantically appropriate HTTP status.
Requires the sqlx feature flag.
sqlx::Error variant | code | HTTP |
|---|---|---|
RowNotFound | NOT_FOUND | 404 |
Database (unique/FK violation) | CONFLICT | 409 |
Database (check violation) | VALIDATION_ERROR | 422 |
Database (other) | DB_ERROR | 500 |
PoolTimedOut / PoolClosed / WorkerCrashed | SERVICE_UNAVAILABLE | 503 |
| everything else | DB_ERROR | 500 |
Source§impl From<ValidationErrors> for ApiError
Available on crate feature validator only.
impl From<ValidationErrors> for ApiError
validator only.Source§fn from(errors: ValidationErrors) -> Self
fn from(errors: ValidationErrors) -> Self
Auto Trait Implementations§
impl Freeze for ApiError
impl RefUnwindSafe for ApiError
impl Send for ApiError
impl Sync for ApiError
impl Unpin for ApiError
impl UnsafeUnpin for ApiError
impl UnwindSafe for ApiError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more