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