Error Reference
Overview
The App Engine has 15 error types. Each subsystem owns its errors. EngineError unifies them for top-level error handling via From impls.
flowchart TD
E["EngineError<br/>(Top-level — converts from all subsystem errors)"] --> C["CommandError<br/>(Command execution)"]
E --> T["TaskError<br/>(Task execution)"]
E --> R["ResourceError<br/>(Resource operations)"]
E --> S["ServiceError<br/>(Service lifecycle)"]
E --> P["PluginError<br/>(Plugin lifecycle/loading)"]
E --> SC["SchedulingError<br/>(Scheduling operations)"]
E --> H["HistoryError<br/>(History operations)"]
E --> CF["ConfigurationError<br/>(Config validation/persistence)"]
E --> PE["PersistenceError<br/>(Storage backend)"]
E --> SE["SerializationError<br/>(Serialization/deserialization)"]
E --> PS["PluginSecurityError<br/>(Permission denial)"]
E --> CX["ContextError<br/>(Context operations)"]
E --> ST["StateError<br/>(State transitions)"]
E --> CO["CommunicationError<br/>(Event handler errors)"]
E --> AE["AsyncError<br/>(Async runtime (with async-runtime feature))"]
1. EngineError
The top-level engine error. All subsystem errors convert to EngineError via From.
Variants
| Variant |
Description |
InvalidLifecycleTransition { from: String, to: String } |
Invalid lifecycle state transition. |
AlreadyInitialized |
Engine is already initialized. |
NotInitialized |
Engine is not initialized. |
AlreadyRunning |
Engine is already running. |
AlreadyStopped |
Engine is already stopped. |
AlreadyDisposed |
Engine is already disposed. |
InitializationFailed(String) |
Initialization failed (reason). |
StartupFailed(String) |
Startup failed (reason). |
ShutdownFailed(String) |
Shutdown failed (reason). |
SubsystemFailure { subsystem: String, reason: String } |
A subsystem reported a failure. |
Display Examples
Invalid lifecycle transition: Created -> Running
Engine is already initialized
Initialization failed: database unreachable
service subsystem failure: Service 3 failed to start: db error
Helpers
EngineError::invalid_transition("Created", "Running")
EngineError::subsystem("service", "Service 3 failed to start")
From Conversions
let _: EngineError = ServiceError::NotFound { id: 1 }.into();
let _: EngineError = PluginError::NotFound { id: 1 }.into();
let _: EngineError = CommandError::UnknownCommand { id: "x".into() }.into();
let _: EngineError = TaskError::NotFound { id: 1 }.into();
let _: EngineError = ResourceError::NotFound { id: 1 }.into();
let _: EngineError = ConfigurationError::NotFound { key: "x".into() }.into();
let _: EngineError = SchedulingError::JobNotFound { id: 1 }.into();
let _: EngineError = HistoryError::NoUndoAvailable.into();
let _: EngineError = CommunicationError::HandlerNotFound { id: 1 }.into();
let _: EngineError = ContextError::NoApplicationContext.into();
Usage
fn do_work(engine: &mut AppEngine) -> Result<(), EngineError> {
engine.service_manager_mut().start_all(&engine.engine_ref())?;
// ServiceError auto-converts to EngineError via From impl
Ok(())
}
match engine.initialize() {
Ok(()) => {},
Err(EngineError::AlreadyInitialized) => { /* continue */ },
Err(EngineError::InvalidLifecycleTransition { from, to }) => {
eprintln!("Invalid: {} -> {}", from, to);
},
Err(EngineError::SubsystemFailure { subsystem, reason }) => {
eprintln!("{} failed: {}", subsystem, reason);
},
Err(e) => eprintln!("Unexpected: {}", e),
}
2. CommandError
Command execution errors.
Variants
| Variant |
Description |
UnknownCommand { id: String } |
No handler registered for the command. |
InvalidArguments(String) |
Handler rejected the input. |
InvalidState |
Command executed in wrong state. |
NotAvailable(String) |
Command not available (reason). |
ExecutionFailed(String) |
Handler execution failed. |
Cancelled |
Command was cancelled. |
PermissionDenied(String) |
Permission denied (reason). |
NoHandler { id: String } |
Handler missing (internal inconsistency). |
AlreadyRegistered { id: String } |
Command already registered. |
Display Examples
Unknown command: app.missing
Invalid arguments: expected String
Command not available: requires admin
Command execution failed: disk full
Command cancelled
Permission denied: insufficient role
No handler registered for command: app.echo
Command already registered: app.echo
When Each Occurs
| Variant |
Triggered by |
UnknownCommand |
execute() with unregistered command ID |
InvalidArguments |
Handler rejects input (wrong type, missing field) |
ExecutionFailed |
Handler returned Err or panicked |
Cancelled |
Command was cancelled |
AlreadyRegistered |
register() with duplicate ID |
NoHandler |
Internal inconsistency (should not happen) |
3. TaskError
Task execution and lifecycle errors.
Variants
| Variant |
Description |
NotFound { id: u64 } |
Task not found. |
UnknownDefinition { id: String } |
Task definition not registered. |
InvalidState { id: u64, current: String, requested: String } |
Invalid state transition. |
NotPausable { id: u64, current: String } |
Task doesn't support pause. |
NotCancellable { id: u64, current: String } |
Task doesn't support cancel. |
AlreadyRunning { id: u64 } |
Task is already running. |
AlreadyCompleted { id: u64 } |
Task is already completed. |
ExecutionFailed { id: u64, reason: String } |
Handler execution failed. |
Cancelled { id: u64 } |
Task was cancelled. |
InvalidDefinition { id: String } |
Invalid task definition. |
AlreadyRegistered { id: String } |
Task definition already registered. |
Display Examples
Task not found: 42
Unknown task definition: export
Task 3 invalid state transition: Pending -> Completed
Task 5 is not pausable (current: Pending)
Task 7 is not cancellable (current: Completed)
Task 9 execution failed: disk full
Task 11 was cancelled
Task definition already registered: render
When Each Occurs
| Variant |
Triggered by |
NotFound |
start/pause/resume/cancel with bogus ID |
UnknownDefinition |
create() with unregistered definition |
InvalidState |
start() on a non-Pending task, etc. |
NotPausable |
pause() on a task without pause support |
NotCancellable |
cancel() on a task without cancel support |
ExecutionFailed |
Handler returned Err or panicked |
AlreadyRegistered |
register() with duplicate ID |
4. ResourceError
Resource operation errors.
Variants
| Variant |
Description |
NotFound { id: u64 } |
Resource not found. |
LoaderNotFound { resource_type: String } |
No loader for the resource type. |
LoadFailed { source: String, reason: String } |
Loading failed. |
InvalidResource { id: u64 } |
Invalid resource. |
AlreadyLoaded { id: u64 } |
Resource already loaded. |
AlreadyReleased { id: u64 } |
Resource already released. |
UnloadFailed { id: u64, reason: String } |
Unload failed. |
InvalidHandle { id: u64 } |
Invalid resource handle. |
NoData { id: u64 } |
Resource has no data. |
ReloadFailed { id: u64, reason: String } |
Reload failed. |
InUse { id: u64 } |
Resource is in use (can't unload). |
Display Examples
Resource not found: 7
No loader for resource type: image
Failed to load resource 'file:///missing.png': file not found
Resource 3 is in use and cannot be unloaded
Invalid resource handle: 99
Failed to reload resource 5: file changed
5. ServiceError
Service lifecycle errors.
Variants
| Variant |
Description |
NotFound { id: u64 } |
Service not found. |
InvalidState { id: u64, current: String, requested: String } |
Invalid state transition. |
AlreadyRegistered { id: String } |
Service already registered. |
StartFailed { id: u64, reason: String } |
Start failed (including panic). |
StopFailed { id: u64, reason: String } |
Stop failed (including panic). |
InitializeFailed { id: u64, reason: String } |
Initialize failed (including panic). |
DisposeFailed { id: u64, reason: String } |
Dispose failed (including panic). |
Display Examples
Service not found: 3
Service 3 invalid state transition: Running -> Initialized
Service already registered: logger
Service 5 failed to start: database unreachable
Service 7 failed to initialize: service panicked: init crashed!
6. PluginError
Plugin lifecycle and loading errors.
Variants
| Variant |
Description |
NotFound { id: u64 } |
Plugin not found. |
InvalidState { id: u64, current: String, requested: String } |
Invalid state transition. |
AlreadyRegistered { id: String } |
Plugin already registered. |
LoadFailed { source: String, reason: String } |
Loading failed. |
InitializeFailed { id: u64, reason: String } |
Initialize failed (including panic). |
StartFailed { id: u64, reason: String } |
Start failed (including panic). |
StopFailed { id: u64, reason: String } |
Stop failed (including panic). |
DisposeFailed { id: u64, reason: String } |
Dispose failed (including panic). |
DependencyNotMet { id: String, dependency: String } |
Dependency not registered. |
Display Examples
Plugin not found: 5
Plugin 5 invalid state transition: Loaded -> Unloaded
Plugin already registered: image-plugin
Failed to load plugin 'image.so': no suitable loader found
Plugin 3 failed to initialize: plugin panicked: init crashed!
Plugin 'a' requires dependency 'b' which is not registered
7. SchedulingError
Scheduling operation errors.
Variants
| Variant |
Description |
JobNotFound { id: u64 } |
Job not found. |
JobAlreadyCancelled { id: u64 } |
Job already cancelled. |
JobAlreadyCompleted { id: u64 } |
Job already completed. |
InvalidState { id: u64, current: String, requested: String } |
Invalid state transition. |
Display Examples
Job not found: 42
Job 42 is already cancelled
Job 42 invalid state: Scheduled -> Completed
8. HistoryError
History operation errors.
Variants
| Variant |
Description |
EntryNotFound { id: u64 } |
History entry not found. |
NoUndoAvailable |
No operations to undo. |
NoRedoAvailable |
No operations to redo. |
TransactionNotActive |
No active transaction. |
TransactionAlreadyActive |
Transaction already active. |
ReplayExhausted |
Replay entries exhausted. |
Display Examples
History entry not found: 42
No undo available
No redo available
No active transaction
Replay entries exhausted
9. ConfigurationError
Configuration validation and persistence errors.
Variants
| Variant |
Description |
ValidationFailed { key: String, reason: String } |
Schema validation failed. |
NotFound { key: String } |
Configuration key not found. |
InvalidType { key: String, expected: String, actual: String } |
Type mismatch. |
LoadFailed { reason: String } |
Configuration load failed. |
SaveFailed { reason: String } |
Configuration save failed. |
Display Examples
Configuration validation failed for 'worker_count': value 0 is below minimum 1
Configuration key not found: missing
Configuration 'count' has invalid type: expected integer, got string
Configuration load failed: file not found
Configuration save failed: permission denied
10. PersistenceError
Storage backend errors.
Variants
| Variant |
Description |
IoError { reason: String } |
I/O error. |
SerializationError { reason: String } |
Serialization error. |
DeserializationError { reason: String } |
Deserialization error. |
KeyNotFound { key: String } |
Key not found. |
BackendNotAvailable |
No backend configured. |
Display Examples
I/O error: permission denied
Serialization error: invalid format
Deserialization error: unexpected EOF
Key not found: app.name
No persistence backend available
From Conversions
let _: PersistenceError = std::io::Error::from(...).into();
11. SerializationError
Serialization and deserialization errors.
Variants
| Variant |
Description |
NoSerializer { type_name: String } |
No serializer registered for type. |
SerializationFailed { type_name: String, reason: String } |
Serialization failed. |
DeserializationFailed { type_name: String, reason: String } |
Deserialization failed. |
TypeMismatch { expected: String, actual: String } |
Type mismatch during downcast. |
Display Examples
No serializer registered for type: my_domain::ExportInput
Failed to serialize my_domain::ExportInput: invalid format
Failed to deserialize my_domain::ExportInput: unexpected EOF
Type mismatch: expected ExportInput, got unknown
12. PluginSecurityError
Permission denial errors.
Variants
| Variant |
Description |
PermissionDenied { plugin_id: String, permission: String } |
Plugin lacks required permission. |
InsufficientPermissions { plugin_id: String, required: u32, actual: u32 } |
Insufficient permissions (bits). |
Display Examples
Plugin 'limited' lacks permission: LOAD_RESOURCES
Plugin 'limited' has insufficient permissions (has 00000001, needs 00000100)
13. ContextError
Context operation errors.
Variants
| Variant |
Description |
NoApplicationContext |
No application context exists. |
SessionNotFound |
Session not found. |
ExecutionNotFound |
Execution not found. |
Display Examples
No application context exists
Session not found
Execution not found
14. StateError
State transition errors.
Variants
| Variant |
Description |
StateNotFound |
State not found in store. |
TransitionMismatch { expected: String, actual: String } |
Current state doesn't match from. |
Display Examples
State not found in store
State transition mismatch: expected Created, got Running
15. CommunicationError
Event handler errors.
Variants
| Variant |
Description |
HandlerNotFound { id: u64 } |
Handler not found. |
SubscriptionNotFound { id: u64 } |
Signal subscription not found. |
AlreadySubscribed { topic: String } |
Already subscribed to topic. |
Display Examples
Event handler not found: 42
Signal subscription not found: 5
Already subscribed to: task.completed
16. AsyncError (with async-runtime feature)
Async runtime errors.
Variants
| Variant |
Description |
RuntimeCreationFailed(String) |
Runtime creation failed. |
TaskJoinError(String) |
Task join failed. |
AsyncExecutionFailed(String) |
Async execution failed. |
Display Examples
Async runtime creation failed: out of memory
Async task join error: task panicked
Async execution failed: future returned error
From Conversions
let _: AsyncError = tokio::task::JoinError::from(...).into();
Error Handling Patterns
Top-Level Error Handling
use app_shell::app_engine::*;
fn main() {
let mut engine = Bootstrap::create()
.unwrap_or_else(|e| {
eprintln!("Bootstrap failed: {}", e);
std::process::exit(1);
});
if let Err(e) = engine.initialize() {
match e {
EngineError::AlreadyInitialized => {
// Continue — already initialized
},
EngineError::SubsystemFailure { subsystem, reason } => {
eprintln!("{} subsystem failed: {}", subsystem, reason);
// A service or plugin failed during initialization
// Engine continues — panic was caught
},
_ => {
eprintln!("Initialization failed: {}", e);
std::process::exit(1);
}
}
}
}
Subsystem-Specific Error Handling
// Command execution
match engine.execute_command(&cmd) {
Ok(result) => { /* handle result */ },
Err(CommandError::UnknownCommand { id }) => {
eprintln!("No command: {}", id);
},
Err(CommandError::ExecutionFailed(msg)) => {
// Could be handler error OR handler panic
eprintln!("Failed: {}", msg);
},
Err(e) => eprintln!("{}", e),
}
// Task execution
match engine.start_task(task_id) {
Ok(result) => { /* handle result */ },
Err(TaskError::NotFound { id }) => eprintln!("Task {} not found", id),
Err(TaskError::InvalidState { current, requested, .. }) => {
eprintln!("Can't {}: {} -> {}", requested, current, requested);
},
Err(TaskError::ExecutionFailed { reason, .. }) => {
// Could be handler error OR handler panic
eprintln!("Failed: {}", reason);
},
Err(e) => eprintln!("{}", e),
}
Converting to EngineError
fn do_work(engine: &mut AppEngine) -> Result<(), EngineError> {
// All subsystem errors auto-convert via From
engine.service_manager_mut().start_all(&engine.engine_ref())?;
// ServiceError → EngineError::SubsystemFailure
engine.execute_command(&cmd)?;
// CommandError → EngineError::SubsystemFailure
engine.start_task(task_id)?;
// TaskError → EngineError::SubsystemFailure
Ok(())
}
Panic-Isolated Errors
When a handler panics, the error message contains "handler panicked: " prefix:
// Task handler panic → TaskError::ExecutionFailed
// Message: "handler panicked: task handler crashed!"
// Command handler panic → CommandError::ExecutionFailed
// Message: "handler panicked: command handler crashed!"
// Service lifecycle panic → ServiceError::*Failed
// Message: "service panicked: service init crashed!"
// Plugin lifecycle panic → PluginError::*Failed
// Message: "plugin panicked: plugin init crashed!"
Detecting Panic-Origin Errors
match engine.start_task(task_id) {
Err(TaskError::ExecutionFailed { reason, .. }) if reason.contains("handler panicked") => {
eprintln!("Handler panicked: {}", reason);
// Can retry, log, or escalate
},
Err(TaskError::ExecutionFailed { reason, .. }) => {
eprintln!("Handler failed: {}", reason);
},
Ok(result) => { /* ... */ },
Err(e) => eprintln!("{}", e),
}
Quick Reference: All Error Types
| Error Type |
Owned By |
Subsystem |
EngineError |
App Engine |
Top-level |
CommandError |
Commands |
Command execution |
TaskError |
Tasks |
Task execution |
ResourceError |
Resources |
Resource operations |
ServiceError |
Services |
Service lifecycle |
PluginError |
Plugins |
Plugin lifecycle |
SchedulingError |
Scheduling |
Job operations |
HistoryError |
History |
Undo/redo/replay |
ConfigurationError |
Configuration |
Config validation |
PersistenceError |
Persistence |
Storage backend |
SerializationError |
Serialization |
Serializer |
PluginSecurityError |
Plugins |
Permission enforcement |
ContextError |
Context |
Context creation |
StateError |
State |
State transitions |
CommunicationError |
Events/Signals |
Handler/subscription |
AsyncError |
Concurrency |
Async runtime (feature) |
Next Steps