pub enum AppError {
Show 19 variants
Config(String),
Io(Error),
Store(String),
SecretStore(String),
Serialization(Error),
Internal(String),
NotFound(String),
Conflict(String),
Authentication(String),
Unauthorized(String),
Forbidden(String),
StepUpRequired(String),
Validation(String),
QuotaExceeded(String),
TrustTaskMissing,
TrustTaskMalformed(String),
TrustTaskMismatch {
expected: String,
received: Option<String>,
},
DomainDisabled {
domain: String,
message: Option<String>,
},
AgentName(AgentNameError),
}Variants§
Config(String)
Io(Error)
Store(String)
SecretStore(String)
Serialization(Error)
Internal(String)
NotFound(String)
Conflict(String)
Authentication(String)
Forbidden(String)
StepUpRequired(String)
The caller is authenticated but the operation requires a higher
assurance level (acr == aal2) than the session currently holds.
Renders to 403 with the distinct body { "error": "step_up_required", "required_acr": "aal2" } so the wallet can
trigger a step-up ceremony rather than treating it as a plain
permission denial.
Validation(String)
QuotaExceeded(String)
TrustTaskMissing
Trust-Task header was absent on a route that requires it.
Renders to 400 Bad Request with body { "error": "TrustTaskMissing" }.
TrustTaskMalformed(String)
Trust-Task header was present but malformed (non-HTTPS, empty,
or contained control characters). Carries the offending value so
callers can debug. Renders to 400 with body
{ "error": "TrustTaskMalformed", "received": "..." }.
TrustTaskMismatch
Trust-Task header was well-formed but did not exact-match the
route’s registered task. Renders to 415 Unsupported Media Type
with body { "error": "TrustTaskMismatch", "expected": "...", "received": "..." }.
DomainDisabled
Resolution attempted against a configured-but-disabled domain.
Per docs/multi-domain-spec.md §3, renders to 503 with the
maintenance-status JSON body { "status": "disabled", "domain": "<name>", "message"?, "eta"? }. Distinct from NotFound —
404 means “we don’t serve this”, 503 means “we serve this but
it’s temporarily unavailable”.
AgentName(AgentNameError)
An agent-name operation (did_ops::set_agent_name and friends) failed
a name-specific precondition. Carries a typed AgentNameError so the
Trust-Task and REST surfaces can map it to a spec error code without
sniffing message prose — the same discipline ValidationKind follows.
Implementations§
Source§impl AppError
impl AppError
Sourcepub fn validation(kind: ValidationKind, msg: impl Into<String>) -> AppError
pub fn validation(kind: ValidationKind, msg: impl Into<String>) -> AppError
Create a tagged validation error.
Sourcepub fn validation_kind(&self) -> ValidationKind
pub fn validation_kind(&self) -> ValidationKind
Classify a Validation error’s kind by its tag prefix.
Sourcepub fn quota_kind(&self) -> QuotaKind
pub fn quota_kind(&self) -> QuotaKind
Classify a QuotaExceeded error’s kind by its content.
Source§impl AppError
impl AppError
Sourcepub fn didcomm_code(&self) -> &'static str
pub fn didcomm_code(&self) -> &'static str
Stable wire-level DIDComm protocol-error code for this AppError.
Backed by ValidationKind tags rather than substring sniffing on
the Display message, so a wording change in any
AppError::Validation("...") literal doesn’t silently re-route
the protocol code. Both DIDComm dispatchers
(messaging::dispatch_did_op and routes/didcomm.rs::dispatch)
call this so the same error always produces the same wire code
regardless of transport.
The mapping:
Unauthorized/Forbidden→e.p.did.unauthorizedQuotaExceeded(Size)→e.p.did.size-exceededQuotaExceeded(Count)→e.p.did.quota-exceededConflict→e.p.did.path-unavailableNotFound→e.p.did.mnemonic-not-foundValidation(InvalidLog)→e.p.did.invalid-logValidation(InvalidPath)→e.p.did.path-invalidValidation(InvalidWitness)→e.p.did.witness-invalidValidation(Other)→e.p.did.validation-error- everything else (5xx-shaped) →
e.p.did.internal-error
Sourcepub fn user_message(&self) -> String
pub fn user_message(&self) -> String
Stable public message intended for HTTP responses. Decoupled from
Display (which tracing/logging uses) so the wire-level contract
doesn’t drift when an AppError(...) literal’s wording changes
elsewhere.
Variants that name internal identifiers (Forbidden may carry a
DID or ACL reason; NotFound may include a mnemonic) collapse
to a fixed string. Variants that are user-input-shaped
(Validation, Conflict, QuotaExceeded) pass the message
through sanitize_user_message so a caller can’t get arbitrary
control characters echoed back. 5xx variants never reach this
path (the response builder short-circuits to a generic body).
Trait Implementations§
Source§impl Error for AppError
impl Error for AppError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl From<AgentNameError> for AppError
impl From<AgentNameError> for AppError
Source§fn from(source: AgentNameError) -> AppError
fn from(source: AgentNameError) -> AppError
Source§impl From<AuthError> for AppError
Conversion from the canonical auth-flow errors in
vti-common into did-hosting’s AppError. Mirrors the
From<AuthError> for vti_common::AppError impl on the
VTI side — the canonical /auth/* handlers raise
vti_common::AuthError variants and each service’s
AppError knows how to render them through its own
IntoResponse plumbing.
impl From<AuthError> for AppError
Conversion from the canonical auth-flow errors in
vti-common into did-hosting’s AppError. Mirrors the
From<AuthError> for vti_common::AppError impl on the
VTI side — the canonical /auth/* handlers raise
vti_common::AuthError variants and each service’s
AppError knows how to render them through its own
IntoResponse plumbing.