systemprompt_extension/
error.rs1use thiserror::Error;
4
5#[derive(Debug, Error)]
6pub enum LoaderError {
7 #[error("Extension '{extension}' requires dependency '{dependency}' which is not registered")]
8 MissingDependency {
9 extension: String,
10 dependency: String,
11 },
12
13 #[error("Extension with ID '{0}' is already registered")]
14 DuplicateExtension(String),
15
16 #[error("Failed to initialize extension '{extension}': {message}")]
17 InitializationFailed { extension: String, message: String },
18
19 #[error("Failed to install schema for extension '{extension}': {message}")]
20 SchemaInstallationFailed { extension: String, message: String },
21
22 #[error("Migration failed for extension '{extension}': {message}")]
23 MigrationFailed { extension: String, message: String },
24
25 #[error(
26 "Migration {version} for extension '{extension}' is not reversible (no down SQL provided)"
27 )]
28 MigrationNotReversible { extension: String, version: u32 },
29
30 #[error("Configuration validation failed for extension '{extension}': {message}")]
31 ConfigValidationFailed { extension: String, message: String },
32
33 #[error("Extension '{extension}' uses reserved API path '{path}'")]
34 ReservedPathCollision { extension: String, path: String },
35
36 #[error("Extension '{extension}' has invalid base path '{path}': must start with /api/")]
37 InvalidBasePath { extension: String, path: String },
38
39 #[error("Circular dependency detected: {chain}")]
40 CircularDependency { chain: String },
41
42 #[error("Dependency cycle detected while ordering extensions: {chain}")]
43 DependencyCycle { chain: String },
44
45 #[error(
46 "Extension '{extension}' migration ALTERs table '{table}' but does not create it in its \
47 schemas() nor declare it in cross_extension_tables(); cross-extension table mutations \
48 must be declared explicitly"
49 )]
50 CrossExtensionAlterUndeclared { extension: String, table: String },
51
52 #[error(
53 "Table '{table}' is created by both extension '{extension_a}' and '{extension_b}'; every \
54 table must be declared by exactly one extension"
55 )]
56 DuplicateTableOwner {
57 table: String,
58 extension_a: String,
59 extension_b: String,
60 },
61
62 #[error(
63 "Extension '{extension}' declares cross_extension_tables() entry '{table}', which is not \
64 a table created by any other loaded extension"
65 )]
66 CrossExtensionTableNotOwned { extension: String, table: String },
67
68 #[error(
69 "Extension '{extension}' seed '{seed}' contains forbidden statement '{statement}'; seeds \
70 may only contain INSERT … ON CONFLICT, UPDATE, MERGE, or WITH … INSERT"
71 )]
72 InvalidSeedStatement {
73 extension: String,
74 seed: String,
75 statement: String,
76 },
77
78 #[error(
79 "Extension '{extension}' seed '{seed}' contains a bare INSERT with no ON CONFLICT clause; \
80 seeds run on every boot and must be idempotent — add ON CONFLICT … DO NOTHING/UPDATE"
81 )]
82 SeedInsertNotIdempotent { extension: String, seed: String },
83
84 #[error("Extension '{extension}' seed '{seed}' failed to parse or apply: {message}")]
85 SeedFailed {
86 extension: String,
87 seed: String,
88 message: String,
89 },
90}
91
92#[derive(Debug, Error)]
93pub enum ConfigError {
94 #[error("Configuration key '{0}' not found")]
95 NotFound(String),
96
97 #[error("Invalid configuration value for '{key}': {message}")]
98 InvalidValue { key: String, message: String },
99
100 #[error("Failed to parse configuration: {0}")]
101 ParseError(String),
102
103 #[error("Schema validation failed: {0}")]
104 SchemaValidation(String),
105}