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::errors::ServicesValidationError`,
15//! `systemprompt_manifest::profile::ProfileError`) via `#[from]`.
16//!
17//! Copyright (c) systemprompt.io — Business Source License 1.1.
18//! See <https://systemprompt.io> for licensing details.
19
20use std::path::PathBuf;
21use systemprompt_identifiers::AgentName;
22use thiserror::Error;
23
24#[derive(Debug, Error)]
25pub enum ConfigLoadError {
26    #[error("profile bootstrap unavailable: {0}")]
27    ProfileBootstrap(#[from] systemprompt_config::ProfileBootstrapError),
28
29    #[error("io error at {path}: {source}")]
30    Io {
31        path: PathBuf,
32        #[source]
33        source: std::io::Error,
34    },
35
36    #[error("yaml parse failure at {path}: {source}")]
37    Yaml {
38        path: PathBuf,
39        #[source]
40        source: serde_yaml::Error,
41    },
42
43    #[error(
44        "include file not found: {include}\nReferenced in: {referrer}\nEither create the file or \
45         remove it from the includes list."
46    )]
47    IncludeNotFound { include: PathBuf, referrer: PathBuf },
48
49    #[error("invalid identifier at {path}: {source}")]
50    InvalidId {
51        path: PathBuf,
52        #[source]
53        source: systemprompt_identifiers::error::IdValidationError,
54    },
55
56    #[error("include cycle detected: {chain}")]
57    IncludeCycle { chain: String },
58
59    #[error("duplicate agent definition: {0}")]
60    DuplicateAgent(String),
61
62    #[error("duplicate MCP server definition: {0}")]
63    DuplicateMcpServer(String),
64
65    #[error("duplicate plugin definition: {0}")]
66    DuplicatePlugin(String),
67
68    #[error("duplicate marketplace definition: {0}")]
69    DuplicateMarketplace(String),
70
71    #[error("duplicate skill definition: {0}")]
72    DuplicateSkill(String),
73
74    #[error("duplicate external agent definition: {0}")]
75    DuplicateExternalAgent(String),
76
77    #[error("duplicate Slack app definition: {0}")]
78    DuplicateSlackApp(String),
79
80    #[error("duplicate Teams app definition: {0}")]
81    DuplicateTeamsApp(String),
82
83    #[error("duplicate provider definition across services includes: {0}")]
84    DuplicateProvider(String),
85
86    #[error(
87        "Services config not initialized. Call ServicesBootstrap::init() after \
88         ProfileBootstrap::init()"
89    )]
90    NotInitialized,
91
92    #[error("Services config already initialized")]
93    AlreadyInitialized,
94
95    #[error("services config validation failed: {0}")]
96    Validation(#[from] systemprompt_models::errors::ServicesValidationError),
97
98    #[error(
99        "include {path} sets `settings:` — settings are only valid in the root config file. Move \
100         the values to the root or remove them from the include."
101    )]
102    IncludeMustNotSetGlobalSettings { path: PathBuf },
103}
104
105#[derive(Debug, Error)]
106pub enum ConfigWriteError {
107    #[error("io error at {path}: {source}")]
108    Io {
109        path: PathBuf,
110        #[source]
111        source: std::io::Error,
112    },
113
114    #[error("yaml serialisation failed: {0}")]
115    YamlEncode(#[from] serde_yaml::Error),
116
117    #[error("Agent file already exists: {0}. Use 'agents edit' to modify.")]
118    AgentFileExists(PathBuf),
119
120    #[error("Agent '{0}' not found in any configuration file")]
121    AgentNotFound(AgentName),
122}
123
124#[derive(Debug, Error)]
125pub enum ExtensionLoadError {
126    #[error("Binary '{name}' not found at {path}")]
127    BinaryNotFound { name: String, path: PathBuf },
128
129    #[error("No manifest.yaml found for extension '{0}' in extensions/")]
130    ManifestMissing(String),
131}
132
133#[derive(Debug, Error)]
134pub enum ProfileLoadError {
135    #[error("io error at {path}: {source}")]
136    Io {
137        path: PathBuf,
138        #[source]
139        source: std::io::Error,
140    },
141
142    #[error(transparent)]
143    Profile(#[from] systemprompt_manifest::profile::ProfileError),
144}
145
146pub type ConfigLoadResult<T> = Result<T, ConfigLoadError>;
147
148pub type ConfigWriteResult<T> = Result<T, ConfigWriteError>;
149
150pub type ExtensionLoadResult<T> = Result<T, ExtensionLoadError>;
151
152pub type ProfileLoadResult<T> = Result<T, ProfileLoadError>;