Error Forge is a comprehensive, zero-dependency error management framework for Rust applications. It simplifies error handling through expressive macros, automatic trait implementations, and extensible error hooks for seamless integration with external logging systems.
Features
- Rich Error Types: Define expressive error types with minimal boilerplate
- ForgeError Trait: Unified interface for all error types with contextual metadata
- Declarative Macros: Generate complete error enums with the
define_errors!
macro
- Error Composition: Combine errors from multiple modules with the
group!
macro
- Derive Macros: Quickly implement errors with
#[derive(ModError)]
- Console Formatting: ANSI color formatting for terminal output with
ConsoleTheme
- Error Hooks: Register callbacks for errors with severity level support
- Zero External Dependencies: Completely standalone with no third-party dependencies
Installation
Add the following to your Cargo.toml
file:
[dependencies]
error-forge = "0.6.3"
Usage
Basic Error Definition
use error_forge::define_errors;
define_errors! {
pub enum DatabaseError {
#[error(display = "Database connection failed: {}", message)]
ConnectionFailed { message: String },
#[error(display = "Query execution failed: {}", message)]
QueryFailed { message: String, query: String },
#[error(display = "Record not found with ID: {}", id)]
RecordNotFound { id: String },
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let error = DatabaseError::connection_failed("Timeout after 30 seconds");
println!("Error kind: {}", error.kind());
println!("Caption: {}", error.caption());
println!("Status code: {}", error.status_code());
Err(Box::new(error))
}
Error Composition with the group!
Macro
use error_forge::{define_errors, group};
define_errors! {
pub enum ApiError {
#[error(display = "Invalid API key")]
InvalidApiKey,
#[error(display = "Rate limit exceeded")]
RateLimitExceeded,
}
}
define_errors! {
pub enum ValidationError {
#[error(display = "Required field {} is missing", field)]
MissingField { field: String },
#[error(display = "Field {} has invalid format", field)]
InvalidFormat { field: String },
}
}
group! {
pub enum AppError {
Api(ApiError),
Validation(ValidationError),
}
}
fn validate_request() -> Result<(), AppError> {
let error = ValidationError::missing_field("username");
Err(error.into())
}
Using Derive Macro
use error_forge::ModError;
#[derive(Debug, ModError)]
#[module_error(kind = "AuthError")]
pub enum AuthError {
#[error(display = "Invalid credentials")]
InvalidCredentials,
#[error(display = "Account locked: {}", reason)]
AccountLocked { reason: String },
#[error(display = "Session expired")]
#[http_status(401)]
SessionExpired,
}
fn login() -> Result<(), AuthError> {
Err(AuthError::InvalidCredentials)
}
Error Hooks for Logging Integration
use error_forge::{AppError, macros::{register_error_hook, ErrorLevel, ErrorContext}};
fn main() {
register_error_hook(|ctx| {
match ctx.level {
ErrorLevel::Info => println!("INFO: {} [{}]", ctx.caption, ctx.kind),
ErrorLevel::Warning => println!("WARN: {} [{}]", ctx.caption, ctx.kind),
ErrorLevel::Error => println!("ERROR: {} [{}]", ctx.caption, ctx.kind),
ErrorLevel::Critical => {
println!("CRITICAL: {} [{}]", ctx.caption, ctx.kind);
if ctx.is_fatal {
send_notification("Critical error occurred", ctx.caption);
}
}
}
});
let _error = AppError::config("Configuration file not found");
}
fn send_notification(level: &str, message: &str) {
println!("Notification sent: {} - {}", level, message);
}
Console Formatting
use error_forge::{AppError, ConsoleTheme};
fn main() {
let error = AppError::config("Database configuration missing");
let theme = ConsoleTheme::new();
println!("{}", theme.format_error(&error));
theme.install_panic_hook();
panic!("Something went wrong!");
}
Advanced Usage
For more detailed documentation and advanced usage examples, refer to the API Documentation.