runifold_workflow/
error.rs1use runifold_agent::AgentError;
2use std::collections::BTreeMap;
3
4use runifold_core::{BudgetExceeded, CheckpointError, ChildRunError, JournalError};
5use thiserror::Error;
6
7use crate::{StepId, WorkflowWaitError};
8
9#[derive(Clone, Debug, Error, Eq, PartialEq)]
11#[non_exhaustive]
12pub enum WorkflowBuildError {
13 #[error("workflow name cannot be empty")]
15 EmptyName,
16 #[error("invalid workflow step identifier `{0}`")]
18 InvalidStepId(String),
19 #[error("workflow step `{0}` is registered more than once")]
21 DuplicateStep(StepId),
22 #[error("workflow requires at least one step")]
24 NoSteps,
25 #[error("workflow version must be greater than zero")]
27 InvalidVersion,
28 #[error("workflow durable timer must be a positive whole-millisecond duration")]
30 InvalidTimerDuration,
31 #[error("workflow signal name must contain 1..=128 portable ASCII characters")]
33 InvalidSignalName,
34 #[error("workflow interrupt prompt must contain 1..=16384 bytes")]
36 InvalidInterruptPrompt,
37 #[error("parallel workflow step `{0}` requires at least two branches")]
39 TooFewParallelBranches(StepId),
40 #[error("race workflow step `{0}` requires at least two branches")]
42 TooFewRaceBranches(StepId),
43 #[error("invalid parallel branch identifier `{0}`")]
45 InvalidParallelBranchId(String),
46 #[error("parallel branch `{branch}` is registered more than once in step `{step}`")]
48 DuplicateParallelBranch {
49 step: StepId,
51 branch: StepId,
53 },
54 #[error(
56 "race branch `{branch}` in step `{step}` cannot abandon capability `{capability}` with external write effects"
57 )]
58 UnsafeRaceCapability {
59 step: StepId,
61 branch: StepId,
63 capability: String,
65 },
66}
67
68#[derive(Debug, Error)]
70#[non_exhaustive]
71pub enum WorkflowStepError {
72 #[error("Agent execution failed: {0}")]
74 Agent(#[from] AgentError),
75 #[error("invalid step input: {0}")]
77 InvalidInput(String),
78 #[error("invalid step output: {0}")]
80 InvalidOutput(String),
81 #[error("step output serialization failed: {0}")]
83 Serialization(#[from] serde_json::Error),
84 #[error("step execution failed: {0}")]
86 Execution(String),
87}
88
89#[derive(Debug, Error)]
91#[non_exhaustive]
92pub enum WorkflowError {
93 #[error(transparent)]
95 Build(#[from] WorkflowBuildError),
96 #[error("workflow step `{step}` requested capability `{capability}` not held by its parent")]
98 AuthorityEscalation {
99 step: StepId,
101 capability: String,
103 },
104 #[error("workflow step `{step}` failed: {source}")]
106 Step {
107 step: StepId,
109 #[source]
111 source: Box<WorkflowStepError>,
112 },
113 #[error("parallel branch `{branch}` in workflow step `{step}` failed: {source}")]
115 ParallelBranch {
116 step: StepId,
118 branch: StepId,
120 #[source]
122 source: Box<WorkflowStepError>,
123 },
124 #[error("every branch in workflow race step `{step}` failed")]
126 RaceAllFailed {
127 step: StepId,
129 failures: BTreeMap<StepId, String>,
131 },
132 #[error("workflow execution was cancelled")]
134 Cancelled,
135 #[error("workflow execution deadline elapsed")]
137 DeadlineExceeded,
138 #[error("durable workflow wait requires a distributed WorkflowWorker")]
140 DurableWaitRequiresWorker,
141 #[error("workflow wake does not match its persisted wait condition")]
143 WakeMismatch,
144 #[error("invalid workflow wait: {0}")]
146 Wait(#[from] WorkflowWaitError),
147 #[error("workflow wait output serialization failed: {0}")]
149 Serialization(#[from] serde_json::Error),
150 #[error("workflow budget exceeded: {0}")]
152 Budget(#[from] BudgetExceeded),
153 #[error("workflow child Run is invalid: {0}")]
155 ChildRun(#[from] ChildRunError),
156 #[error("checkpoint contains ambiguous in-flight workflow step `{step}`")]
158 AmbiguousCheckpoint {
159 step: StepId,
161 },
162 #[error("workflow checkpoint does not match the current workflow definition")]
164 CheckpointIdentityMismatch,
165 #[error("workflow checkpoint usage is incompatible with the supplied run")]
167 CheckpointUsageMismatch,
168 #[error("workflow observability failed: {0}")]
170 Journal(#[from] JournalError),
171 #[error("workflow checkpoint failed: {0}")]
173 Checkpoint(#[from] CheckpointError),
174}