muster/domain/config/error.rs
1use std::path::PathBuf;
2
3use thiserror::Error;
4
5use crate::domain::{
6 agent_session::{AgentProcessId, AgentSessionId},
7 process::{AgentTool, ProcessKind},
8 value::{ProcessName, ProjectName},
9};
10
11/// Errors from workspace configuration and project registry operations.
12#[derive(Debug, Error)]
13pub enum ConfigError {
14 /// The configuration file could not be read from disk.
15 #[error("could not read config file {path}: {source}")]
16 Read {
17 /// Path that failed to load.
18 path: PathBuf,
19 /// Underlying I/O error.
20 source: std::io::Error,
21 },
22 /// The configuration file could not be written to disk.
23 #[error("could not write config file {path}: {source}")]
24 Write {
25 /// Path that failed to write.
26 path: PathBuf,
27 /// Underlying I/O error.
28 source: std::io::Error,
29 },
30 /// No writable config directory could be located on this platform.
31 #[error("no config directory is available")]
32 NoConfigDir,
33 /// The session-state file uses a schema newer than this binary understands.
34 #[error("unsupported agent-session state version {0}")]
35 UnsupportedAgentSessionVersion(u8),
36 /// A lifecycle update referenced a session no longer present in state.
37 #[error("agent session '{0}' is not present in session state")]
38 AgentSessionNotFound(AgentSessionId),
39 /// A lifecycle event came from a provider that does not own the session.
40 #[error(
41 "agent session '{id}' belongs to {expected}, but received a lifecycle event from {reported}"
42 )]
43 AgentSessionProviderMismatch {
44 /// Session whose provider rejected the lifecycle event.
45 id: AgentSessionId,
46 /// Provider recorded when the session was created.
47 expected: AgentTool,
48 /// Provider that emitted the lifecycle event.
49 reported: AgentTool,
50 },
51 /// A lifecycle event came from a descendant instead of the managed provider process.
52 #[error(
53 "agent session '{id}' belongs to process {expected:?}, but received a lifecycle event from process {reported}"
54 )]
55 AgentSessionProcessMismatch {
56 /// Session whose provider process rejected the lifecycle event.
57 id: AgentSessionId,
58 /// Process currently owning the managed agent session.
59 expected: Option<AgentProcessId>,
60 /// Process that emitted the lifecycle event.
61 reported: AgentProcessId,
62 },
63 /// A concurrent Muster instance already owns the managed agent session.
64 #[error("agent session '{id}' is already owned by live process {owner}")]
65 AgentSessionAlreadyOwned {
66 /// Session whose ownership claim was rejected.
67 id: AgentSessionId,
68 /// Live provider process retaining ownership.
69 owner: AgentProcessId,
70 },
71 /// A legacy registry entry has no stable location outside its original
72 /// launch directory.
73 #[error(
74 "registered project '{name}' uses unsupported relative config path {path:?}; edit or remove it in projects.yml"
75 )]
76 RelativeProjectConfig {
77 /// Registered project whose config path is ambiguous.
78 name: ProjectName,
79 /// Relative config path stored by an earlier version.
80 path: PathBuf,
81 },
82 /// The configuration was not valid YAML or violated the schema.
83 #[error("could not parse config: {0}")]
84 Parse(#[from] serde_yaml_ng::Error),
85 /// A non-command process configured command-only graceful shutdown.
86 #[error("{kind} process '{name}' configures stop, which is only valid for commands")]
87 InvalidStopPolicy {
88 /// Section containing the invalid process.
89 kind: ProcessKind,
90 /// Name of the invalid process.
91 name: ProcessName,
92 },
93}