#[api_error]Expand description
Attribute macro for automatically generating HTTP error responses.
This macro automatically implements axum::response::IntoResponse for error enums,
mapping each variant to an appropriate HTTP status code. Use doc comments with
/// {code}: {description} format to specify status codes for variants.
§Basic Usage
use stonehm_macros::api_error;
#[api_error]
enum ApiError {
/// 404: User not found
UserNotFound { id: u32 },
/// 400: Invalid input provided
InvalidInput { message: String },
/// 401: Authentication required
Unauthorized,
/// 403: Access forbidden
Forbidden,
// Variants without doc comments default to 500 Internal Server Error
DatabaseError,
NetworkTimeout,
}§Generated Implementation
The macro automatically generates:
IntoResponseimplementation for HTTP responsesSerializeimplementation for JSON serializationStonehmSchemaimplementation for OpenAPI documentation- Maps each variant to its specified status code
- Uses 500 Internal Server Error for variants without doc comments
- Serializes the error as JSON in the response body
§Supported Status Codes
Common HTTP status codes you can use:
- 200 OK
- 201 Created
- 204 No Content
- 400 Bad Request
- 401 Unauthorized
- 403 Forbidden
- 404 Not Found
- 409 Conflict
- 422 Unprocessable Entity
- 500 Internal Server Error
- 502 Bad Gateway
- 503 Service Unavailable
§Examples
§Basic Error Enum
#[api_error]
#[derive(Serialize)]
enum UserError {
/// 404: User not found
NotFound { id: u32 },
/// 400: Invalid user data
InvalidData { field: String, reason: String },
}§With Custom Serialization
#[api_error]
#[derive(Serialize)]
#[serde(tag = "error", content = "details")]
enum ApiError {
/// 401: Missing or invalid authentication token
#[serde(rename = "auth_required")]
AuthRequired,
/// 403: User lacks required permissions
#[serde(rename = "access_denied")]
AccessDenied { required_role: String },
}§Usage in Handlers
/// Update user information
#[api_handler]
async fn update_user(
axum::extract::Path(id): axum::extract::Path<u32>,
Json(data): Json<UpdateUserRequest>
) -> Result<Json<User>, UserError> {
if id == 0 {
return Err(UserError::NotFound { id });
}
if data.name.is_empty() {
return Err(UserError::InvalidData {
message: "Name cannot be empty".to_string()
});
}
Ok(Json(User { id, name: data.name }))
}§Requirements
- The error enum must also have
#[derive(Serialize)]or implementSerializemanually - Each variant’s doc comment should start with a 3-digit HTTP status code followed by a colon
- The macro will automatically implement
axum::response::IntoResponse - The macro will register the error schema for OpenAPI documentation