Skip to main content

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}