pub enum RuntimeError {
Show 15 variants
Replay(ReplayError),
Store(StoreError),
Model(Error),
RequestEncode(Error),
RecordedResponseDecode(Error),
RunAlreadyStarted {
run_id: RunId,
},
UnknownRun {
run_id: RunId,
},
NotParked {
run_id: RunId,
status: String,
},
ResumeInputRejected(String),
InvalidLabels(String),
NotReconcilable {
run_id: RunId,
status: String,
},
CallInFlight {
tool: String,
idempotency_key: String,
holder: RunId,
holder_seq: u64,
},
IdempotencyKeyCollision {
tool: String,
idempotency_key: String,
origin: RunId,
origin_seq: u64,
},
CommitmentUnreadable {
tool: String,
idempotency_key: String,
origin: RunId,
origin_seq: u64,
},
AlreadyTerminal {
run_id: RunId,
status: String,
},
}Expand description
What can go wrong while driving a run.
Replay, Store, and Model each spell out their inner error’s Display
directly in their own message ("replay: {0}" and so on) rather than
leaning on thiserror’s #[source]/#[from] chaining for that text. A
field that is both interpolated into the message AND wired as the
Error::source() gets printed twice by anything that walks the source
chain on top of Display (anyhow’s {:#}, {:?}, and the like): once
embedded in this variant’s own message, once again as the chain’s next
link. Plain From impls below give ? the same conversion #[from]
would without also handing these three a chained source, so the detail
appears exactly once no matter how the caller prints the error.
Variants§
Replay(ReplayError)
The replay layer refused to continue: divergence, a malformed log, or a dangling write intent that needs human reconciliation.
Store(StoreError)
The event store failed to persist or read an event.
Model(Error)
A live model call failed after the client’s own retries. The run’s log is intact (the intent, if any, is recorded), so the run can be recovered later; the model intent will be re-issued safely.
RequestEncode(Error)
A model request could not be serialized to JSON for hashing.
RecordedResponseDecode(Error)
A recorded model response could not be decoded back into a typed response. This means the log holds something this build cannot read, which is a storage or versioning fault, not orchestration divergence.
RunAlreadyStarted
start was called for a run id that already has recorded history.
UnknownRun
The named run has no recorded history at all.
NotParked
resume was called on a run whose log does not end at a suspension
or budget crossing.
Fields
ResumeInputRejected(String)
The resume input did not satisfy the recorded suspension schema (or, for a budget crossing, the budget-extension shape).
InvalidLabels(String)
The labels a run is about to be created with violate the sanity
bounds (too many, or a key/value over its length cap). See
crate::validate_labels. Surfaces only on a genuinely fresh
begin; a replayed run never re-checks the labels it already
recorded.
NotReconcilable
resolve was called on a run that is not awaiting reconciliation. The
hand-recorded completion is only ever appended to a run whose log ends
at a dangling write intent; every other state is a caller mistake.
Fields
CallInFlight
A keyed call could not proceed because another run holds the same
(tool, idempotency key) identity and has not finished with it.
The holder is either running right now or died mid-call. Either way the effect may or may not have happened, and this run has no way to find out and no right to try: proceeding would be exactly the second execution the key exists to prevent. So the call refuses, and it refuses before recording anything, which leaves this run’s log untouched and the run re-runnable once the holder is finished or reconciled.
The resolution lives in the holding run, never here. Finish it, or
reconcile its dangling write with salvor resolve, and then run this
one again.
Fields
IdempotencyKeyCollision
Two different calls presented the same (tool, idempotency key)
identity with different inputs.
The key is a promise that two calls are the same call. Different inputs under one key break that promise, and there is no safe reading of it: deduplicating would hand this call an output computed from somebody else’s arguments, and executing would perform an effect the key says has already been performed. So neither happens and the key’s author is told.
The fix is in the key, not here. A key must be specific enough to name
one effect: "pay_claim:wreck-9931", not "pay_claim".
Fields
CommitmentUnreadable
A commitment pointed at a completion that its run’s log does not hold.
The store said an identity was settled at a position, and reading that run’s log (chain verification included) did not produce the completion there. That is a damaged store, not a race: a settlement and its completion are written as one unit, so one cannot exist without the other. Reported rather than worked around, because the alternative would be executing an effect the store believes already happened.
Fields
AlreadyTerminal
abandon was called on a run that already reached a terminal event
(completed, failed, or previously abandoned). A terminal run is already
at rest; there is nothing left to retire, so the operator action is
refused rather than appending a second terminal.
Trait Implementations§
Source§impl Debug for RuntimeError
impl Debug for RuntimeError
Source§impl Display for RuntimeError
impl Display for RuntimeError
Source§impl Error for RuntimeError
impl Error for RuntimeError
1.30.0 · 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()