Skip to main content

zeph_subagent/
error.rs

1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4/// All errors that can arise during sub-agent lifecycle operations.
5///
6/// [`SubAgentError`] is the single error type for the entire `zeph-subagent` crate.
7/// Every fallible public function returns `Result<_, SubAgentError>`.
8///
9/// # Examples
10///
11/// ```rust
12/// use zeph_subagent::{SubAgentDef, SubAgentError};
13///
14/// let err = SubAgentDef::parse("missing frontmatter").unwrap_err();
15/// assert!(matches!(err, SubAgentError::Parse { .. }));
16/// ```
17#[derive(Debug, thiserror::Error)]
18#[non_exhaustive]
19pub enum SubAgentError {
20    /// Frontmatter parsing failed (malformed YAML/TOML or missing delimiters).
21    #[error("parse error in {path}: {reason}")]
22    Parse { path: String, reason: String },
23
24    /// Definition semantics are invalid (e.g. empty name, conflicting tool policies).
25    #[error("invalid definition: {0}")]
26    Invalid(String),
27
28    /// No definition or running agent with the requested name or ID was found.
29    #[error("agent not found: {0}")]
30    NotFound(String),
31
32    /// The background task could not be spawned (OS or tokio error).
33    #[error("spawn failed: {0}")]
34    Spawn(String),
35
36    /// The manager's concurrency limit is exhausted; no new agents can be spawned.
37    #[error("concurrency limit reached (active: {active}, max: {max})")]
38    ConcurrencyLimit { active: usize, max: usize },
39
40    /// The agent loop was cancelled via its [`tokio_util::sync::CancellationToken`].
41    #[error("cancelled")]
42    Cancelled,
43
44    /// A slash-command string (`/agent`, `/agents`) could not be parsed.
45    #[error("invalid command: {0}")]
46    InvalidCommand(String),
47
48    /// An I/O operation on a transcript file failed.
49    #[error("transcript error: {0}")]
50    Transcript(String),
51
52    /// An ID prefix matched more than one transcript; provide a longer prefix.
53    #[error("ambiguous id prefix '{0}': matches {1} agents")]
54    AmbiguousId(String, usize),
55
56    /// Resume was requested for an agent that is still running.
57    #[error("agent '{0}' is still running; cancel it first or wait for completion")]
58    StillRunning(String),
59
60    /// A memory directory could not be created or resolved.
61    #[error("memory error for agent '{name}': {reason}")]
62    Memory { name: String, reason: String },
63
64    /// A filesystem I/O error unrelated to transcripts.
65    #[error("I/O error at {path}: {reason}")]
66    Io { path: String, reason: String },
67
68    /// The underlying LLM provider returned an error during the agent loop.
69    #[error("LLM call failed: {0}")]
70    Llm(String),
71
72    /// A channel send (status watch, secret approval) failed.
73    #[error("channel send failed: {0}")]
74    Channel(String),
75
76    /// The tokio task panicked and the join handle propagated the panic.
77    #[error("task panicked: {0}")]
78    TaskPanic(String),
79
80    /// The recursion depth for nested sub-agent spawning exceeded the configured limit.
81    #[error("max spawn depth exceeded (depth: {depth}, max: {max})")]
82    MaxDepthExceeded { depth: u32, max: u32 },
83
84    /// Worktree creation or cwd setup failed during agent spawn.
85    ///
86    /// This error is returned when `permissions.worktree = true` and the worktree
87    /// manager fails to create a dedicated worktree or cannot restore the working
88    /// directory.  The agent loop never starts in this case (INV-4).
89    #[error("worktree setup failed: {0}")]
90    WorktreeSetup(String),
91}