#[non_exhaustive]pub enum DurableError {
Show 17 variants
ReplayDivergence {
step_id: StepId,
},
AmbiguityPolicyRequired {
step: &'static str,
},
JournalUnavailable,
PayloadTooLarge {
size: u64,
max: u64,
},
Decode {
context: &'static str,
},
ReplayIntegrity,
ControlIntegrity,
StepCapExceeded {
cap: u32,
},
EncryptionRequired {
context: &'static str,
},
UnsupportedEntryKind {
kind: &'static str,
},
Storage {
op: &'static str,
source: Box<dyn Error + Send + Sync>,
},
StepFailed {
step: &'static str,
source: Box<dyn Error + Send + Sync>,
},
AmbiguousEffect {
step_id: StepId,
},
Serialize {
step: &'static str,
},
UnknownPromise,
PromiseRejected,
ExecutionLocked {
execution_id: ExecutionId,
holder_pid: u32,
},
}Expand description
An error raised by the durable execution layer.
The enum is #[non_exhaustive]: follow-up issues add variants as runtime behavior lands, and
downstream match expressions must keep a wildcard arm.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
ReplayDivergence
The replayed step’s descriptor fingerprint did not match the fingerprint journaled for this
StepId (INV-3). The execution is discarded and restarted fresh rather than returning a
result for a structurally different step.
AmbiguityPolicyRequired
A destructive or security-relevant ExactlyOnceGuarded step was constructed without an
explicit ambiguity policy. The safety decision must be made at the call site, not deferred
to a runtime default.
The journal writer did not acknowledge an append within the configured timeout, or is otherwise unreachable. The calling path degrades to non-durable mode rather than hanging (INV-12).
PayloadTooLarge
A payload exceeded the configured max_payload_bytes limit. Enforced on both append and
read; it fails closed and never panics (INV-11).
Fields
Decode
A journal entry could not be decoded: corrupt, truncated, or written under an unknown wire format version. Fails closed.
ReplayIntegrity
AEAD authentication failed when opening a sealed payload: the entry was forged, moved to a different step, or replayed under a different execution. Fails closed.
ControlIntegrity
A control entry’s row-level HMAC (INV-8) did not verify against a recomputed value: the row
was forged, relocated to a different step/execution, or is missing its HMAC even though the
backend is keyed. Fails closed like ReplayIntegrity, but for
HMAC-authenticated control entries (EffectIntent) rather than AEAD-sealed payloads.
StepCapExceeded
An execution exceeded the hard per-execution step cap and was aborted rather than allowed to grow unboundedly.
EncryptionRequired
AEAD payload encryption was disabled (encrypt_payload = false) for a deployment where it
is mandatory — a non-local backend or a shared database (INV-8). The DB-file trust boundary
does not hold in multi-client environments, so this fails closed at startup.
Fields
UnsupportedEntryKind
A journal entry of a kind whose persistence is provided by a higher layer not yet wired into this backend revision. Promise, timer, and checkpoint entries land with the promise/timer and retention layers; until then the backend fails closed rather than silently dropping the entry’s kind-specific state.
Storage
A journal storage operation failed at the database layer (connection, migration, or query).
The static op names the failing operation; the underlying database error is attached as
the error source. Per INV-5 the Display message carries only the operation name — the
boxed source never contains plaintext payloads, since every bind is ciphertext, a hash, or a
non-secret descriptor.
Fields
StepFailed
A step’s operation closure returned an error on a fresh execution. The step did not complete,
so no StepResult is journaled; on a later resume the step re-runs (or, for a guarded effect,
its OnAmbiguous policy applies). The closure’s own error is attached
as the source.
Fields
AmbiguousEffect
A guarded step resumed inside the ambiguous window (an EffectIntent is journaled but no
StepResult) and its policy is OnAmbiguous::Fail: the layer
refuses to guess whether the irreversible effect fired and surfaces the decision to the
operator instead of re-running or skipping it.
Serialize
A step result could not be serialized into journal bytes before sealing. The step’s value is
the consumer’s serializable type, so this indicates a faulty Serialize implementation; it
fails closed rather than journaling a partial payload. Per INV-5 only the step name is named.
UnknownPromise
A promise resolution referenced a promise that has no durable_promises row — either never
created, or pruned. Fails closed rather than silently succeeding. Per INV-5 the raw
PromiseId is semi-sensitive and is therefore not embedded in the message.
PromiseRejected
A promise resolution presented a resolver token that did not match the stored hash (INV-9).
The comparison is constant-time, and neither the presented token nor the raw PromiseId
appears in the message (INV-5). The pending promise is left untouched.
ExecutionLocked
crate::backend::LocalBackend::open_execution_exclusive found another process already
holding the execution’s advisory lock (INV-15, #6122).
Two processes deriving the same ExecutionId (e.g. two CLI instances pointed at the same
memory.sqlite_path and the same ConversationId) can no longer both drive it
concurrently: the second process gets this error instead of silently racing the first into
ReplayDivergence/ReplayIntegrity failures. Distinct from those two variants so callers
(and operators reading logs) can tell “another live process owns this execution” apart from
“the journal itself is corrupt or was tampered with”.
Fields
execution_id: ExecutionIdThe execution whose lock is already held.
Trait Implementations§
Source§impl Debug for DurableError
impl Debug for DurableError
Source§impl Display for DurableError
impl Display for DurableError
Source§impl Error for DurableError
impl Error for DurableError
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<CipherError> for DurableError
impl From<CipherError> for DurableError
Source§fn from(err: CipherError) -> Self
fn from(err: CipherError) -> Self
Lift a cipher failure into the crate-wide error, preserving fail-closed semantics.
An authentication failure is a replay-integrity violation; a structural or key-selection failure is a decode failure. Both fail closed — no plaintext is ever returned.
Auto Trait Implementations§
impl !RefUnwindSafe for DurableError
impl !UnwindSafe for DurableError
impl Freeze for DurableError
impl Send for DurableError
impl Sync for DurableError
impl Unpin for DurableError
impl UnsafeUnpin for DurableError
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more