Skip to main content

zeph_orchestration/
error.rs

1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use zeph_subagent::SubAgentError;
5
6/// All error variants produced by the orchestration subsystem.
7///
8/// Variants are exhaustive — callers that match on this type should use a
9/// `_ => …` arm to stay robust against future additions.
10///
11/// # Fail-open policy
12///
13/// LLM-backed steps (verification, replan) are always fail-open: on failure
14/// they log a warning and continue rather than returning an error. Only
15/// structural invariant violations and hard configuration errors propagate as
16/// `Err`.
17///
18/// # Examples
19///
20/// ```rust
21/// use zeph_orchestration::OrchestrationError;
22///
23/// fn describe(err: &OrchestrationError) -> &'static str {
24///     match err {
25///         OrchestrationError::CycleDetected => "graph has a cycle",
26///         OrchestrationError::Disabled => "orchestration is off",
27///         _ => "other orchestration error",
28///     }
29/// }
30///
31/// let err = OrchestrationError::CycleDetected;
32/// assert_eq!(describe(&err), "graph has a cycle");
33/// ```
34#[derive(Debug, thiserror::Error)]
35pub enum OrchestrationError {
36    /// Orchestration is disabled in configuration.
37    #[error("orchestration is disabled")]
38    Disabled,
39
40    /// The LLM planner failed to produce a valid task graph.
41    #[error("planning failed: {0}")]
42    PlanningFailed(String),
43
44    /// The task graph structure is invalid (e.g. wrong task-id invariant, bad reference).
45    #[error("invalid graph: {0}")]
46    InvalidGraph(String),
47
48    /// A cycle was detected during topological sort of the task graph.
49    #[error("cycle detected in task graph")]
50    CycleDetected,
51
52    /// A `TaskId` or task title lookup yielded no result.
53    #[error("task not found: {0}")]
54    TaskNotFound(String),
55
56    /// No agent in the available pool can be routed to a task.
57    #[error("no agent available for task: {0}")]
58    NoAgentAvailable(String),
59
60    /// A `GraphId` could not be found in persistence.
61    #[error("graph not found: {0}")]
62    GraphNotFound(String),
63
64    /// An internal scheduler invariant was violated.
65    #[error("scheduler error: {0}")]
66    Scheduler(String),
67
68    /// Result aggregation failed and the fallback path also failed.
69    #[error("aggregation failed: {0}")]
70    AggregationFailed(String),
71
72    /// A database read/write or serialization error in graph persistence.
73    #[error("persistence error: {0}")]
74    Persistence(String),
75
76    /// A task exceeded its per-task wall-clock timeout.
77    #[error("task timed out: {0}")]
78    TaskTimeout(String),
79
80    /// The scheduler or a task was canceled by the caller.
81    #[error("canceled")]
82    Canceled,
83
84    /// A `/plan` CLI command could not be parsed.
85    #[error("invalid command: {0}")]
86    InvalidCommand(String),
87
88    /// Hard invariant violation during verification (e.g. cycle detected after `inject_tasks`).
89    ///
90    /// Never used for LLM call failures — those are fail-open and only log a warning.
91    #[error("verification failed: {0}")]
92    VerificationFailed(String),
93
94    /// A required configuration value is missing or out of range.
95    #[error("invalid configuration: {0}")]
96    InvalidConfig(String),
97
98    /// Propagated error from a sub-agent execution.
99    #[error(transparent)]
100    SubAgent(#[from] SubAgentError),
101}