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 content source definition: {0}")]
64    DuplicateContentSource(String),
65
66    #[error("duplicate external agent definition: {0}")]
67    DuplicateExternalAgent(String),
68
69    #[error("services config validation failed: {0}")]
70    Validation(String),
71
72    #[error(
73        "include {path} sets `settings:` — settings are only valid in the root config file. Move \
74         the values to the root or remove them from the include."
75    )]
76    IncludeMustNotSetGlobalSettings { path: PathBuf },
77}
78
79#[derive(Debug, Error)]
80pub enum ConfigWriteError {
81    #[error("io error at {path}: {source}")]
82    Io {
83        path: PathBuf,
84        #[source]
85        source: std::io::Error,
86    },
87
88    #[error("yaml serialisation failed: {0}")]
89    YamlEncode(#[from] serde_yaml::Error),
90
91    #[error("Agent file already exists: {0}. Use 'agents edit' to modify.")]
92    AgentFileExists(PathBuf),
93
94    #[error("Agent '{0}' not found in any configuration file")]
95    AgentNotFound(String),
96}
97
98#[derive(Debug, Error)]
99pub enum ExtensionLoadError {
100    #[error("Binary '{name}' not found at {path}")]
101    BinaryNotFound { name: String, path: PathBuf },
102
103    #[error("No manifest.yaml found for extension '{0}' in extensions/")]
104    ManifestMissing(String),
105}
106
107pub type ConfigLoadResult<T> = Result<T, ConfigLoadError>;
108
109pub type ConfigWriteResult<T> = Result<T, ConfigWriteError>;
110
111pub type ExtensionLoadResult<T> = Result<T, ExtensionLoadError>;
112
113#[derive(Debug, Error)]
114pub enum ProfileLoadError {
115    #[error("io error at {path}: {source}")]
116    Io {
117        path: PathBuf,
118        #[source]
119        source: std::io::Error,
120    },
121
122    #[error(transparent)]
123    Profile(#[from] systemprompt_models::profile::ProfileError),
124}
125
126pub type ProfileLoadResult<T> = Result<T, ProfileLoadError>;