systemprompt_runtime/
error.rs1use std::path::PathBuf;
17
18use systemprompt_agent::AgentError;
19use systemprompt_analytics::AnalyticsError;
20use systemprompt_config::paths::PathError;
21use systemprompt_config::{
22 ConfigError as ProfileConfigError, ProfileBootstrapError, SecretsBootstrapError,
23};
24use systemprompt_content::ContentError;
25use systemprompt_extension::LoaderError;
26use systemprompt_files::FilesError;
27use systemprompt_governance::authz::AuthzError;
28use systemprompt_governance::policy::GovernanceEngineError;
29use systemprompt_identifiers::SecretName;
30use systemprompt_loader::{BundleError, ConfigLoadError};
31use systemprompt_marketplace::managed::ManagedError;
32use systemprompt_mcp::McpDomainError;
33use systemprompt_models::errors::GlobalConfigError;
34use systemprompt_oauth::OauthError;
35use systemprompt_security::keys::TokenAuthorityError;
36use systemprompt_traits::{BoxedSource, FileStorageError, RepositoryError};
37use systemprompt_users::UserError;
38use thiserror::Error;
39
40pub type RuntimeResult<T> = Result<T, RuntimeError>;
41
42#[derive(Debug, Error)]
43pub enum RuntimeError {
44 #[error(transparent)]
45 Profile(#[from] ProfileConfigError),
46
47 #[error(transparent)]
48 ProfileBootstrap(#[from] ProfileBootstrapError),
49
50 #[error(transparent)]
51 Config(#[from] GlobalConfigError),
52
53 #[error(transparent)]
54 Paths(#[from] PathError),
55
56 #[error(transparent)]
57 Files(#[from] FilesError),
58
59 #[error(transparent)]
60 Users(#[from] UserError),
61
62 #[error(transparent)]
63 Repository(#[from] RepositoryError),
64
65 #[error(transparent)]
66 Analytics(#[from] AnalyticsError),
67
68 #[error(transparent)]
69 Mcp(#[from] McpDomainError),
70
71 #[error(transparent)]
72 Agent(#[from] AgentError),
73
74 #[error(transparent)]
75 Content(#[from] ContentError),
76
77 #[error(transparent)]
78 Oauth(#[from] OauthError),
79
80 #[error(transparent)]
81 Loader(#[from] LoaderError),
82
83 #[error(transparent)]
84 Governance(#[from] GovernanceEngineError),
85
86 #[error(transparent)]
87 Managed(#[from] ManagedError),
88
89 #[error(transparent)]
90 Secrets(#[from] SecretsBootstrapError),
91
92 #[error("services config: {0}")]
93 ServicesConfig(#[from] ConfigLoadError),
94
95 #[error("services bundle: {0}")]
96 ServicesBundle(#[from] BundleError),
97
98 #[error("services bundle {name} has no cached fetch state")]
99 ServicesBundleNotCached { name: String },
100
101 #[error("services bundle {name} manifest: {source}")]
102 ServicesBundleManifest {
103 name: String,
104 #[source]
105 source: BundleError,
106 },
107
108 #[error("services authz reconcile: {0}")]
109 ServicesReconcile(#[source] AuthzError),
110
111 #[error("services reconcile state: {0}")]
112 ServicesReconcileState(#[source] BundleError),
113
114 #[error("signing key init: {0}")]
115 Signing(#[from] TokenAuthorityError),
116
117 #[error("authz bootstrap: {0}")]
118 Authz(#[from] AuthzError),
119
120 #[error("storage root {} probe: {source}", .path.display())]
121 StorageProbe {
122 path: PathBuf,
123 #[source]
124 source: FileStorageError,
125 },
126
127 #[error("storage root {} did not read back what was written", .path.display())]
128 StorageReadBack { path: PathBuf },
129
130 #[error("storage.credentials names secret '{name}', which the secrets store does not hold")]
131 StorageCredentialMissing { name: SecretName },
132
133 #[error("storage.credentials secret '{name}' does not hold the backend's credential: {source}")]
134 StorageCredential {
135 name: SecretName,
136 #[source]
137 source: serde_json::Error,
138 },
139
140 #[error("storage backend requires storage.bucket")]
141 StorageBucketMissing,
142
143 #[error("storage.backend 's3' requires storage.credentials: {{ secret: NAME }}")]
144 StorageS3CredentialsRequired,
145
146 #[error("storage endpoint: {0}")]
147 StorageEndpoint(#[source] url::ParseError),
148
149 #[error("storage HTTP client: {0}")]
150 StorageHttp(#[source] reqwest::Error),
151
152 #[error(
153 "Configured system admin '{username}' was not found in the users table. Run `systemprompt \
154 admin bootstrap` first."
155 )]
156 SystemAdminNotFound { username: String },
157
158 #[error(
159 "Configured system admin '{username}' exists but is not active. Re-activate the user \
160 before starting the platform."
161 )]
162 SystemAdminInactive { username: String },
163
164 #[error(
165 "Configured system admin '{username}' exists but does not carry the 'admin' role. Grant \
166 the role before starting the platform."
167 )]
168 SystemAdminMissingRole { username: String },
169
170 #[error(
171 "Configured GeoIP database at '{path}' could not be loaded: {source}. Fix or remove \
172 paths.geoip_database from the profile."
173 )]
174 GeoIpUnreadable {
175 path: String,
176 #[source]
177 source: BoxedSource,
178 },
179
180 #[error(
181 "database schema is behind this binary (migrations skipped at boot): {} extension(s) not \
182 installed [{}], {} pending migration(s) [{}], {} checksum drift(s) [{}]; run \
183 'systemprompt infra db migrate --profile {profile}' and restart",
184 .fresh.len(),
185 .fresh.join(", "),
186 .pending.len(),
187 .pending.join(", "),
188 .drift.len(),
189 .drift.join(", ")
190 )]
191 SchemaBehind {
192 profile: String,
193 fresh: Vec<String>,
194 pending: Vec<String>,
195 drift: Vec<String>,
196 },
197
198 #[error(
199 "database schema was contracted by a newer release: {} migration(s) marked `@compat: \
200 breaking` [{}] cannot be served by this binary; stop this release's pods and run the \
201 newer one (profile {profile})",
202 .migrations.len(),
203 .migrations.join(", ")
204 )]
205 SchemaBreaksThisRelease {
206 profile: String,
207 migrations: Vec<String>,
208 },
209
210 #[error("DATABASE_URL is empty")]
211 EmptyDatabaseUrl,
212
213 #[error("DATABASE_URL must be a postgres:// or postgresql:// URL")]
214 UnsupportedDatabaseUrl,
215}