runifold_workflow/
error.rs1use runifold_agent::AgentError;
2use std::collections::BTreeMap;
3
4use runifold_core::{BudgetExceeded, BudgetReservationMismatch, CheckpointError, JournalError};
5use thiserror::Error;
6
7use crate::StepId;
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("parallel workflow step `{0}` requires at least two branches")]
30 TooFewParallelBranches(StepId),
31 #[error("race workflow step `{0}` requires at least two branches")]
33 TooFewRaceBranches(StepId),
34 #[error("invalid parallel branch identifier `{0}`")]
36 InvalidParallelBranchId(String),
37 #[error("parallel branch `{branch}` is registered more than once in step `{step}`")]
39 DuplicateParallelBranch {
40 step: StepId,
42 branch: StepId,
44 },
45 #[error(
47 "race branch `{branch}` in step `{step}` cannot abandon capability `{capability}` with external write effects"
48 )]
49 UnsafeRaceCapability {
50 step: StepId,
52 branch: StepId,
54 capability: String,
56 },
57}
58
59#[derive(Debug, Error)]
61#[non_exhaustive]
62pub enum WorkflowStepError {
63 #[error("Agent execution failed: {0}")]
65 Agent(#[from] AgentError),
66 #[error("invalid step input: {0}")]
68 InvalidInput(String),
69 #[error("invalid step output: {0}")]
71 InvalidOutput(String),
72 #[error("step output serialization failed: {0}")]
74 Serialization(#[from] serde_json::Error),
75 #[error("step execution failed: {0}")]
77 Execution(String),
78}
79
80#[derive(Debug, Error)]
82#[non_exhaustive]
83pub enum WorkflowError {
84 #[error(transparent)]
86 Build(#[from] WorkflowBuildError),
87 #[error("workflow step `{step}` requested capability `{capability}` not held by its parent")]
89 AuthorityEscalation {
90 step: StepId,
92 capability: String,
94 },
95 #[error("workflow step `{step}` failed: {source}")]
97 Step {
98 step: StepId,
100 #[source]
102 source: Box<WorkflowStepError>,
103 },
104 #[error("parallel branch `{branch}` in workflow step `{step}` failed: {source}")]
106 ParallelBranch {
107 step: StepId,
109 branch: StepId,
111 #[source]
113 source: Box<WorkflowStepError>,
114 },
115 #[error("every branch in workflow race step `{step}` failed")]
117 RaceAllFailed {
118 step: StepId,
120 failures: BTreeMap<StepId, String>,
122 },
123 #[error("workflow execution was cancelled")]
125 Cancelled,
126 #[error("workflow execution deadline elapsed")]
128 DeadlineExceeded,
129 #[error("workflow budget exceeded: {0}")]
131 Budget(#[from] BudgetExceeded),
132 #[error("workflow budget reservation is invalid: {0}")]
134 BudgetReservation(#[from] BudgetReservationMismatch),
135 #[error("checkpoint contains ambiguous in-flight workflow step `{step}`")]
137 AmbiguousCheckpoint {
138 step: StepId,
140 },
141 #[error("workflow checkpoint does not match the current workflow definition")]
143 CheckpointIdentityMismatch,
144 #[error("workflow checkpoint usage is incompatible with the supplied run")]
146 CheckpointUsageMismatch,
147 #[error("workflow observability failed: {0}")]
149 Journal(#[from] JournalError),
150 #[error("workflow checkpoint failed: {0}")]
152 Checkpoint(#[from] CheckpointError),
153}