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, WorkflowReviewError, 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("workflow step `{step}` review failed: {source}")]
115 Review {
116 step: StepId,
118 #[source]
120 source: WorkflowReviewError,
121 },
122 #[error("workflow step `{step}` was rejected after {attempts} generation attempt(s): {reason}")]
124 RemediationRejected {
125 step: StepId,
127 attempts: u32,
129 reason: String,
131 },
132 #[error("workflow step `{step}` exhausted remediation after {attempts} generation attempt(s)")]
134 RemediationExhausted {
135 step: StepId,
137 attempts: u32,
139 },
140 #[error("parallel branch `{branch}` in workflow step `{step}` failed: {source}")]
142 ParallelBranch {
143 step: StepId,
145 branch: StepId,
147 #[source]
149 source: Box<WorkflowStepError>,
150 },
151 #[error("every branch in workflow race step `{step}` failed")]
153 RaceAllFailed {
154 step: StepId,
156 failures: BTreeMap<StepId, String>,
158 },
159 #[error("workflow execution was cancelled")]
161 Cancelled,
162 #[error("workflow execution deadline elapsed")]
164 DeadlineExceeded,
165 #[error("durable workflow wait requires a distributed WorkflowWorker")]
167 DurableWaitRequiresWorker,
168 #[error("workflow wake does not match its persisted wait condition")]
170 WakeMismatch,
171 #[error("invalid workflow wait: {0}")]
173 Wait(#[from] WorkflowWaitError),
174 #[error("workflow wait output serialization failed: {0}")]
176 Serialization(#[from] serde_json::Error),
177 #[error("workflow budget exceeded: {0}")]
179 Budget(#[from] BudgetExceeded),
180 #[error("workflow child Run is invalid: {0}")]
182 ChildRun(#[from] ChildRunError),
183 #[error("checkpoint contains ambiguous in-flight workflow step `{step}`")]
185 AmbiguousCheckpoint {
186 step: StepId,
188 },
189 #[error("workflow checkpoint does not match the current workflow definition")]
191 CheckpointIdentityMismatch,
192 #[error("workflow checkpoint usage is incompatible with the supplied run")]
194 CheckpointUsageMismatch,
195 #[error("workflow observability failed: {0}")]
197 Journal(#[from] JournalError),
198 #[error("workflow checkpoint failed: {0}")]
200 Checkpoint(#[from] CheckpointError),
201}