1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum Error {
5 #[error("not found: {0}")]
6 NotFound(String),
7
8 #[error("validation error: {0}")]
9 Validation(String),
10
11 #[error("permission denied: {0}")]
12 PermissionDenied(String),
13
14 #[error("storage error: {0}")]
15 Storage(String),
16
17 #[error("storage error: {message}")]
18 StorageSource {
19 message: String,
20 #[source]
21 source: Box<dyn std::error::Error + Send + Sync>,
22 },
23
24 #[error("index error: {0}")]
25 Index(String),
26
27 #[error("backend '{backend}' does not support capability '{capability}': {detail}")]
33 BackendUnsupported {
34 backend: String,
35 capability: String,
36 detail: String,
37 },
38
39 #[error(
45 "embedder not configured for '{requested}' recall on backend '{backend}': \
46 semantic recall requires a configured embedder (OpenAI HTTP or local ONNX); \
47 the noop embedder returns no vectors — refusing to silently return empty"
48 )]
49 EmbedderNotConfigured { requested: String, backend: String },
50
51 #[error("index error: {message}")]
52 IndexSource {
53 message: String,
54 #[source]
55 source: Box<dyn std::error::Error + Send + Sync>,
56 },
57
58 #[error("embedding error: {0}")]
59 Embedding(String),
60
61 #[error("embedding error: {message}")]
62 EmbeddingSource {
63 message: String,
64 #[source]
65 source: Box<dyn std::error::Error + Send + Sync>,
66 },
67
68 #[error("internal error: {0}")]
69 Internal(String),
70}
71
72impl From<duckdb::Error> for Error {
73 fn from(e: duckdb::Error) -> Self {
74 Error::Storage(e.to_string())
75 }
76}
77
78impl From<serde_json::Error> for Error {
79 fn from(e: serde_json::Error) -> Self {
80 Error::Internal(e.to_string())
81 }
82}
83
84impl From<reqwest::Error> for Error {
85 fn from(e: reqwest::Error) -> Self {
86 Error::Embedding(e.to_string())
87 }
88}
89
90pub type Result<T> = std::result::Result<T, Error>;