Skip to main content

systemprompt_loader/
error.rs

1//! Error types raised by the loader infrastructure.
2//!
3//! Three thiserror-derived enums cover the public surface:
4//!
5//! - [`ConfigLoadError`] — services-config reading, YAML parsing, include
6//!   resolution, and validation failures.
7//! - [`ConfigWriteError`] — file creation, agent CRUD, and config-file editing
8//!   failures.
9//! - [`ExtensionLoadError`] — manifest discovery and registry lookups.
10//!
11//! All three implement `std::error::Error` and compose with upstream
12//! errors (`std::io::Error`, `serde_yaml::Error`,
13//! `systemprompt_config::ProfileBootstrapError`,
14//! `systemprompt_models::ServicesValidationError`,
15//! `systemprompt_models::ProfileValidationError`) via `#[from]`.
16
17use std::path::PathBuf;
18use thiserror::Error;
19
20#[derive(Debug, Error)]
21pub enum ConfigLoadError {
22    #[error("profile bootstrap unavailable: {0}")]
23    ProfileBootstrap(#[from] systemprompt_config::ProfileBootstrapError),
24
25    #[error("io error at {path}: {source}")]
26    Io {
27        path: PathBuf,
28        #[source]
29        source: std::io::Error,
30    },
31
32    #[error("yaml parse failure at {path}: {source}")]
33    Yaml {
34        path: PathBuf,
35        #[source]
36        source: serde_yaml::Error,
37    },
38
39    #[error(
40        "include file not found: {include}\nReferenced in: {referrer}\nEither create the file or \
41         remove it from the includes list."
42    )]
43    IncludeNotFound { include: PathBuf, referrer: PathBuf },
44
45    #[error("include cycle detected: {chain}")]
46    IncludeCycle { chain: String },
47
48    #[error("duplicate agent definition: {0}")]
49    DuplicateAgent(String),
50
51    #[error("duplicate MCP server definition: {0}")]
52    DuplicateMcpServer(String),
53
54    #[error("duplicate plugin definition: {0}")]
55    DuplicatePlugin(String),
56
57    #[error("duplicate marketplace definition: {0}")]
58    DuplicateMarketplace(String),
59
60    #[error("duplicate skill definition: {0}")]
61    DuplicateSkill(String),
62
63    #[error("duplicate external agent definition: {0}")]
64    DuplicateExternalAgent(String),
65
66    #[error("duplicate Slack app definition: {0}")]
67    DuplicateSlackApp(String),
68
69    #[error("duplicate Teams app definition: {0}")]
70    DuplicateTeamsApp(String),
71
72    #[error("services config validation failed: {0}")]
73    Validation(String),
74
75    #[error(
76        "include {path} sets `settings:` — settings are only valid in the root config file. Move \
77         the values to the root or remove them from the include."
78    )]
79    IncludeMustNotSetGlobalSettings { path: PathBuf },
80}
81
82#[derive(Debug, Error)]
83pub enum ConfigWriteError {
84    #[error("io error at {path}: {source}")]
85    Io {
86        path: PathBuf,
87        #[source]
88        source: std::io::Error,
89    },
90
91    #[error("yaml serialisation failed: {0}")]
92    YamlEncode(#[from] serde_yaml::Error),
93
94    #[error("Agent file already exists: {0}. Use 'agents edit' to modify.")]
95    AgentFileExists(PathBuf),
96
97    #[error("Agent '{0}' not found in any configuration file")]
98    AgentNotFound(String),
99}
100
101#[derive(Debug, Error)]
102pub enum ExtensionLoadError {
103    #[error("Binary '{name}' not found at {path}")]
104    BinaryNotFound { name: String, path: PathBuf },
105
106    #[error("No manifest.yaml found for extension '{0}' in extensions/")]
107    ManifestMissing(String),
108}
109
110#[derive(Debug, Error)]
111pub enum ProfileLoadError {
112    #[error("io error at {path}: {source}")]
113    Io {
114        path: PathBuf,
115        #[source]
116        source: std::io::Error,
117    },
118
119    #[error(transparent)]
120    Profile(#[from] systemprompt_models::profile::ProfileError),
121}
122
123pub type ConfigLoadResult<T> = Result<T, ConfigLoadError>;
124
125pub type ConfigWriteResult<T> = Result<T, ConfigWriteError>;
126
127pub type ExtensionLoadResult<T> = Result<T, ExtensionLoadError>;
128
129pub type ProfileLoadResult<T> = Result<T, ProfileLoadError>;