#[non_exhaustive]pub enum StepError {
Show 14 variants
Effect(EffectError),
Policy(PolicyError),
Store(StoreError),
Encoding(Error),
Tool(ToolError),
Undecidable {
key: EffectKey,
recovery: Recovery,
detail: String,
},
NonDeterminism {
seq: Seq,
expected: EffectKey,
actual: EffectKey,
},
Budget(BudgetExceeded),
Suspended(SuspendReason),
Denied {
action: String,
resource: String,
reason: String,
},
GroupFootprint {
group: String,
detail: String,
},
GroupAborted {
what: String,
},
GroupUnsettled {
group: String,
detail: String,
},
ReplayOverrun {
actual: EffectKey,
},
}Expand description
Failure surfaced to a skill through StepCtx.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Effect(EffectError)
Policy(PolicyError)
Store(StoreError)
Encoding(Error)
Tool(ToolError)
A tool call could not be prepared: the tool is not in the operator’s catalogue, or the arguments do not match what it declared.
The same conversion SkillError::Tool provides, one level down,
and it is load-bearing for the same reason. sink_with is how a
governed tool call is written — the closure hands back whatever
building the effect produced — and BuildsEffect accepts a
Result only when its error converts to this type. Without this
variant the trait’s stated purpose (“ToolCall::prepare, which
refuses a tool the catalogue does not hold, returns the Result it
already produces”) was a capability nothing could use, and the
published snippet that exercises it did not compile.
A refusal here dispatched nothing, so it fails the step rather than leaving doubt: the catalogue was consulted before any call left.
Undecidable
The outcome of an effect cannot be determined, and its declared
Recovery forbids guessing.
Reached two ways, which are the same situation from different
directions: a crash landed between “sent” and “recorded”, or the call
itself failed InDoubt. Either way the journal
cannot distinguish “never applied” from “applied, acknowledgement lost”,
and for anything that mutates, the runtime escalates rather than guess.
A distinct variant rather than a message, because the executor quarantines on it — and a run’s disposition must not hinge on the wording of a string.
NonDeterminism
Surfaced when replay finds the recorded run took a different path.
Budget(BudgetExceeded)
A limit stopped the run before it spent more.
Not a fault: the run did what it was told, and what it was told included a ceiling. Distinct from an ordinary failure so an operator can tell “this needs a bigger budget” from “this is broken”.
Suspended(SuspendReason)
Not a failure. The run is waiting for something that has not happened, and its frame has been persisted.
Propagate it with ?. A skill that catches this turns a durable wait
into a silent hang: the subscription stays registered, the event
eventually arrives, and it resumes a run that has already decided it
finished. It is modelled as an error only because that is how control
leaves a skill — the run is healthy.
Denied
Policy refused the effect.
Separate from Budget because the two are answered differently: a limit
is raised, a rule is argued with. Collapsing them would put “ask for more
quota” and “you are not allowed to do this” behind one message.
GroupFootprint
A member did not fit the group it was added to.
A footprint violation, a mutating effect declared as a read, a nested group, or an empty footprint. Every one of these is caught before the effect runs, which is the only time catching it is free.
GroupAborted
A group was taken back whole, and nothing it did is standing.
Not a quarantine and not a silent failure: every reversible member was
reversed, no deferred member ran, and what says which condition
stopped it. A caller may handle this and carry on, which is the point of
grouping in the first place.
GroupUnsettled
A group could be neither committed nor taken back.
A reversal failed, or a member is in doubt. The run is quarantined, because a partially unwound group is a state nobody declared and no later code can reason about. This is the honest report of the situation that other systems surface as a success with a warning.
ReplayOverrun
Strict replay reached the end of history and the code asked for another effect. The recorded run did less than this code does — divergence that ordered key comparison alone cannot see, because there is nothing left to compare against.
Trait Implementations§
Source§impl Error for StepError
impl Error for StepError
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<BudgetExceeded> for StepError
impl From<BudgetExceeded> for StepError
Source§fn from(source: BudgetExceeded) -> Self
fn from(source: BudgetExceeded) -> Self
Source§impl From<EffectError> for StepError
impl From<EffectError> for StepError
Source§fn from(source: EffectError) -> Self
fn from(source: EffectError) -> Self
Source§impl From<PolicyError> for StepError
impl From<PolicyError> for StepError
Source§fn from(source: PolicyError) -> Self
fn from(source: PolicyError) -> Self
Source§impl From<StepError> for SkillError
impl From<StepError> for SkillError
Source§impl From<StoreError> for StepError
impl From<StoreError> for StepError
Source§fn from(source: StoreError) -> Self
fn from(source: StoreError) -> Self
Auto Trait Implementations§
impl !RefUnwindSafe for StepError
impl !UnwindSafe for StepError
impl Freeze for StepError
impl Send for StepError
impl Sync for StepError
impl Unpin for StepError
impl UnsafeUnpin for StepError
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
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