charon-error
Structured error handling for Rust with rich error reports, data sensitivity labels, panic capture, and GitLab issue integration.
Named after Charon, the Greek ferryman of the dead across the river Styx. This crate ferries your program from a running state to a graceful death, collecting every detail along the way.
Features
- Error chains — Stack multiple errors with
ErrorReportto preserve the full context from root cause to top-level failure - Panic hooks — Capture panics and display human-readable error messages with
setup_panic!andsetup_panic_simple! - Issue submission — Generate pre-filled GitLab issue URLs directly from errors so users can report bugs with few clicks
- Sensitivity labels — Tag data as
Public,Private,Internal, orConfidentialto control what information gets shared in reports - Tracing integration — Works with the
tracingcrate. Use#[instrument]and span traces are captured automatically in error frames - Flexible formatting — Configure output detail level (Compact, Medium, Full, Debug) and indentation style
Example Output
PANIC: A panic occurred during execution.
* Message: 'Error: `Called `ResultExt::unwrap_error()` on an `Err` value`'
* Path: 'src/main.rs:58:21'
PANIC: The application encountered an error it could not recover from.
{
last_error: 'Error: `Called `ResultExt::unwrap_error()` on an `Err` value`',
unique_id: 'IpRUIEGnbEh1r58c14jc',
frames: [
{
message: 'No such file or directory (os error 2)',
source_location: src/cli/config.rs:15:10,
span_trace: [
charon_demo::cli::config::read_config at (src/cli/config.rs:7:0),
charon_demo::cli::start_server at (src/cli.rs:82:0),
charon_demo::cli::start at (src/cli.rs:35:0),
],
attachments: {},
date_time: 2026-02-27T21:56:38.787453133+00:00,
},
{
message: 'The config file failed to load correctly.',
source_location: src/cli/config.rs:15:10,
span_trace: [
charon_demo::cli::config::read_config at (src/cli/config.rs:7:0),
charon_demo::cli::start_server at (src/cli.rs:82:0),
charon_demo::cli::start at (src/cli.rs:35:0),
],
attachments: {
file_path: '../config.toml',
},
date_time: 2026-02-27T21:56:38.787580742+00:00,
},
{
message: 'Error: `Called `ResultExt::unwrap_error()` on an `Err` value`',
source_location: src/main.rs:58:21,
span_trace: [],
attachments: {},
date_time: 2026-02-27T21:56:38.787617912+00:00,
},
],
}
┌──────────────────────────┐
│ Open/Submit Bug Report │
└──────────────────────────┘
NOTE: For span_trace to be filled in, you need to register a tracing::Subscriber
This can be done though the tracing-subscriber crate or by using charon-logging.
PANIC: A panic occurred during execution.
* Message: 'Error: `Called `ResultExt::unwrap_error()` on an `Err` value`'
* Path: 'src/main.rs:58:21'
PANIC: The application encountered an error it could not recover from.
If you report this we might be able to fix this in the future.
Error: `Called `ResultExt::unwrap_error()` on an `Err` value`
Panic Info:
## Summary:
```hcl
{
last_error: 'Error: `Called `ResultExt::unwrap_error()` on an `Err` value`',
unique_id: 'zyzIoan0VCBur1AxeQZx',
frames: [
{
message: 'No such file or directory (os error 2)',
source_location: src/cli/config.rs:15:10,
span_trace: [
charon_demo::cli::config::read_config at (src/cli/config.rs:7:0),
charon_demo::cli::start_server at (src/cli.rs:82:0),
charon_demo::cli::start at (src/cli.rs:35:0),
],
attachments: {},
},
{
message: 'The config file failed to load correctly.',
source_location: src/cli/config.rs:15:10,
span_trace: [
charon_demo::cli::config::read_config at (src/cli/config.rs:7:0),
charon_demo::cli::start_server at (src/cli.rs:82:0),
charon_demo::cli::start at (src/cli.rs:35:0),
],
attachments: {
file_path: '../config.toml',
},
},
{
message: 'Error: `Called `ResultExt::unwrap_error()` on an `Err` value`',
source_location: src/main.rs:58:21,
span_trace: [],
attachments: {},
},
],
}
```
## Debug info:
### Backtrace:
```
1: ErrorFrame::new
2: ErrorReport::push_error
3: charon_demo::main
4: backtrace::__rust_begin_short_backtrace
5: lang_start::{{closure}}
6: rt::lang_start_internal
7: main
8: __libc_start_call_main => ./csu/../sysdeps/nptl/libc_start_call_main.h:58
9: __libc_start_main_impl => ./csu/../csu/libc-start.c:360
10: _start
```
### System:
* Application version: 0.3.0
* System: linux x86_64
Please report this error. Issue title: `Error: `Called `ResultExt::unwrap_error()` on an `Err` value``
- Step 1: Check if error report already exists: https://gitlab.com/%3Cproject_path%3E/%3Cproject_name%3E/-/issues/?sort=created_date&state=all&in=TITLE&search=Error%3A+%60Called+%60ResultExt%3A%3Aunwrap_error%28%29%60+on+an+%60Err%60+value%60
- Step 2: Report issue (if it does not already exists):
- Open Pre-created Report Link:
---
https://gitlab.com/%3Cproject_path%3E/%3Cproject_name%3E/issues/new?...
```

Installation
Add to your Cargo.toml:
[]
= "0.3"
Quick Start
use *;
ResultER<T> is a type alias for Result<T, ErrorReport>. The ResultExt trait (imported via the prelude)
adds .change_context(), .error_attach(), and .unwrap_error() to any Result or Option.
Error Context and Attachments
Adding Context
Use .change_context() to wrap errors with higher-level meaning:
use *;
Attaching Data
Attach diagnostic data to errors with sensitivity labels:
use *;
Sensitivity Labels
ErrorSensitivityLabel controls who can see attached data:
| Level | Data Owner | Other Users | Internal | Encrypted |
|---|---|---|---|---|
Public |
yes | yes | yes | no |
Private |
yes | no | yes | no |
PrivateConfidential |
yes | no | no | yes |
Internal |
no | no | yes | no |
Confidential |
no | no | yes | yes |
HighlyConfidential |
no | no | yes | yes |
Note: Encryption is not implemented yet.
Panic Hooks
Full Panic Hook with Issue Submission
use *;
use *;
When a panic occurs:
- Known errors: Displays a friendly message from
check_if_common_errors - Unknown errors (debug build): Shows the full error report with a clickable link to create a GitLab issue
- Unknown errors (release build): Shows a user-friendly message with report instructions
Simple Panic Hook
For applications that do not need issue submission:
use *;
This panic hook is mainly for when the more full featured panic hook is to much and just want to setup a simple hook. This hook can also be used as a fallback panic hook. Output is much simpler and faster, for example:
PANIC: The application encountered an error it could not recover from.
* Message: 'Error: `Called `ResultExt::unwrap_error()` on an `Err` value`'
* Path: 'src/main.rs:72:21'
Tracing Integration
charon-error integrates with the tracing crate. Annotate functions with #[instrument] and span traces are automatically captured in each error frame:
use *;
The error report will include the span trace showing the call chain through process_request and validate_user.
Roadmap
- GitHub issue submission support
- Encryption for
ConfidentialandHighlyConfidentialdata - Configurable global formatting settings
Use of AI in this project
This project was hand written before AI. We will be using AI to assist in development. However ALL code is manually reviewed and improve. Example uses of AI: documentation, verification, testing, as double check, ...
License
The code in this project is licensed under the MIT or Apache 2.0 license.
All contributions, code and documentation, to this project will be similarly licensed.