Error Handling
AdonisJS-inspired typed error system with HTTP status semantics.
RokError Enum
#![allow(unused)]
fn main() {
use rok_utils::RokError;
let err = RokError::NotFound("User #42".into());
assert_eq!(err.code(), "E_NOT_FOUND");
assert_eq!(err.status(), 404);
assert!(err.is_self_handled());
}
Error Codes
| Code | Status | Description |
|---|---|---|
E_NOT_FOUND | 404 | Resource not found |
E_UNAUTHORIZED | 401 | Authentication required |
E_FORBIDDEN | 403 | Access denied |
E_VALIDATION_FAILURE | 422 | Input validation failed |
E_TOO_MANY_REQUESTS | 429 | Rate limit exceeded |
E_INTERNAL | 500 | Internal server error |
Result Extensions
context
Add context to any error:
#![allow(unused)]
fn main() {
use rok_utils::{RokResultExt, RokError};
fn find_user(id: u64) -> Result<String, RokError> {
if id == 42 {
Ok("Alice".to_string())
} else {
Err(RokError::NotFound(format!("User #{id}")))
}
}
let result = find_user(42).context("Database query failed");
assert!(result.is_ok());
}
or_not_found
Convert None to NotFound error:
#![allow(unused)]
fn main() {
use rok_utils::{RokResultExt, RokError};
let users = vec!["Alice", "Bob"];
let user = users.get(0).or_not_found("User at index 0");
assert_eq!(user.unwrap(), "Alice");
}
Validation Errors
#![allow(unused)]
fn main() {
use rok_utils::RokError;
fn validate_email(email: &str) -> Result<(), RokError> {
if email.contains('@') {
Ok(())
} else {
Err(RokError::ValidationFailure {
field: "email".to_string(),
reason: "Must contain @".to_string(),
})
}
}
let result = validate_email("invalid");
assert!(matches!(result, Err(RokError::ValidationFailure { .. })));
}
Handling Different Errors
#![allow(unused)]
fn main() {
use rok_utils::RokError;
fn handle_error(err: &RokError) -> String {
match err {
RokError::NotFound(msg) => format!("404: {}", msg),
RokError::ValidationFailure { field, reason } => {
format!("Validation error on {}: {}", field, reason)
}
RokError::Unauthorized(msg) => format!("401: {}", msg),
_ => format!("Error: {}", err.code()),
}
}
}