1#[derive(Debug, thiserror::Error)]
6pub enum MemoryError {
7 #[error("Database error: {0}")]
9 Database(#[from] rusqlite::Error),
10
11 #[error("Embedding request failed: {0}")]
13 EmbeddingRequest(#[from] reqwest::Error),
14
15 #[error("Embedding provider returned {actual} dimensions, expected {expected}")]
17 DimensionMismatch { expected: usize, actual: usize },
18
19 #[error("Invalid embedding data: expected {expected_bytes} bytes, got {actual_bytes}")]
21 InvalidEmbedding {
22 expected_bytes: usize,
23 actual_bytes: usize,
24 },
25
26 #[error("Embedding model mismatch: database has '{stored}', config specifies '{configured}'")]
28 ModelMismatch { stored: String, configured: String },
29
30 #[error("Session not found: {0}")]
32 SessionNotFound(String),
33
34 #[error("Fact not found: {0}")]
36 FactNotFound(String),
37
38 #[error("Document not found: {0}")]
40 DocumentNotFound(String),
41
42 #[error("Embedding provider unavailable: {0}")]
44 EmbedderUnavailable(String),
45
46 #[error("Migration failed at version {version}: {reason}")]
48 MigrationFailed { version: u32, reason: String },
49
50 #[error("HNSW index error: {0}")]
52 HnswError(String),
53
54 #[error("Invalid HNSW key format: {0}")]
56 InvalidKey(String),
57
58 #[error("Quantization error: {0}")]
60 QuantizationError(String),
61
62 #[error("Storage path error: {0}")]
64 StorageError(String),
65
66 #[error("Index integrity check failed: {in_sqlite_not_hnsw} items in SQLite but not HNSW, {in_hnsw_not_sqlite} items in HNSW but not SQLite")]
68 IntegrityError {
69 in_sqlite_not_hnsw: usize,
70 in_hnsw_not_sqlite: usize,
71 },
72
73 #[error(
75 "Schema version {found} is ahead of max supported {supported} — upgrade semantic-memory"
76 )]
77 SchemaAhead {
78 found: u32,
80 supported: u32,
82 },
83
84 #[error("Content too large: {size} bytes exceeds limit of {limit} bytes")]
86 ContentTooLarge {
87 size: usize,
89 limit: usize,
91 },
92
93 #[error("Namespace '{namespace}' has {count} facts, limit is {limit}")]
95 NamespaceFull {
96 namespace: String,
98 count: usize,
100 limit: usize,
102 },
103
104 #[error("Database size limit exceeded: current footprint is {current} bytes, limit is {limit} bytes")]
106 DatabaseSizeLimitExceeded {
107 current: u64,
109 limit: u64,
111 },
112
113 #[error("Episode not found: {0}")]
115 EpisodeNotFound(String),
116
117 #[error("Pool reader acquisition timed out after {elapsed_ms}ms (pool size: {pool_size})")]
119 PoolTimeout {
120 elapsed_ms: u64,
122 pool_size: usize,
124 },
125
126 #[error("Invalid configuration for '{field}': {reason}")]
128 InvalidConfig {
129 field: &'static str,
131 reason: String,
133 },
134
135 #[error("Corrupt data in {table} ({row_id}): {detail}")]
137 CorruptData {
138 table: &'static str,
140 row_id: String,
142 detail: String,
144 },
145
146 #[error("Invalid import envelope: {reason}")]
148 ImportInvalid {
149 reason: String,
151 },
152
153 #[error("Import envelope already ingested: {envelope_id}")]
155 ImportDuplicate {
156 envelope_id: String,
158 },
159
160 #[error(
162 "Import requires digest migration or receipt repair for {source_envelope_id}: {detail}"
163 )]
164 ImportMigrationRequired {
165 source_envelope_id: String,
167 detail: String,
169 },
170
171 #[error("{0}")]
173 Other(String),
174}
175
176impl MemoryError {
177 pub fn kind(&self) -> &'static str {
179 match self {
180 Self::Database(_) => "database",
181 Self::EmbeddingRequest(_) => "embedding_request",
182 Self::DimensionMismatch { .. } => "dimension_mismatch",
183 Self::InvalidEmbedding { .. } => "invalid_embedding",
184 Self::ModelMismatch { .. } => "model_mismatch",
185 Self::SessionNotFound(_) => "session_not_found",
186 Self::FactNotFound(_) => "fact_not_found",
187 Self::DocumentNotFound(_) => "document_not_found",
188 Self::EpisodeNotFound(_) => "episode_not_found",
189 Self::PoolTimeout { .. } => "pool_timeout",
190 Self::EmbedderUnavailable(_) => "embedder_unavailable",
191 Self::MigrationFailed { .. } => "migration_failed",
192 Self::HnswError(_) => "hnsw_error",
193 Self::InvalidKey(_) => "invalid_key",
194 Self::QuantizationError(_) => "quantization_error",
195 Self::StorageError(_) => "storage_error",
196 Self::IntegrityError { .. } => "integrity_error",
197 Self::SchemaAhead { .. } => "schema_ahead",
198 Self::ContentTooLarge { .. } => "content_too_large",
199 Self::NamespaceFull { .. } => "namespace_full",
200 Self::DatabaseSizeLimitExceeded { .. } => "database_size_limit_exceeded",
201 Self::InvalidConfig { .. } => "invalid_config",
202 Self::CorruptData { .. } => "corrupt_data",
203 Self::ImportInvalid { .. } => "import_invalid",
204 Self::ImportDuplicate { .. } => "import_duplicate",
205 Self::ImportMigrationRequired { .. } => "import_migration_required",
206 Self::Other(_) => "other",
207 }
208 }
209}