rustbrain_core/error.rs
1//! Typed errors for the rustbrain library boundary.
2//!
3//! CLI code may wrap these in `anyhow`; library consumers should match on
4//! [`BrainError`] directly so callers can distinguish “brain missing” from I/O
5//! or schema mismatches.
6
7use std::path::PathBuf;
8
9/// Error type returned by all public `rustbrain-core` APIs.
10///
11/// Variants map roughly to subsystems: storage, mmap cache, FTS, indexing, and
12/// portable bundles. Display messages are stable enough for CLI stderr; the
13/// enum itself is not yet `#[non_exhaustive]` so minor releases may add variants
14/// carefully (consider matching with a wildcard in long-lived apps).
15#[derive(Debug, thiserror::Error)]
16pub enum BrainError {
17 /// Filesystem or OS I/O failure.
18 #[error("I/O error: {0}")]
19 Io(#[from] std::io::Error),
20
21 /// Underlying SQLite / rusqlite error (constraints, SQL, busy, etc.).
22 #[error("SQLite error: {0}")]
23 Sqlite(#[from] rusqlite::Error),
24
25 /// JSON serialization or deserialization failure (bundles, markers, registry).
26 #[error("JSON error: {0}")]
27 Json(#[from] serde_json::Error),
28
29 /// No `.brain/db.sqlite` at the expected path (call [`crate::Brain::create`] or `sync` first).
30 #[error("brain not found at {path}")]
31 BrainNotFound {
32 /// Path to the missing `.brain` directory (or parent).
33 path: PathBuf,
34 },
35
36 /// `.brain` exists but is structurally invalid.
37 #[error("invalid brain directory: {path}: {reason}")]
38 InvalidBrain {
39 /// Path that failed validation.
40 path: PathBuf,
41 /// Human-readable reason.
42 reason: String,
43 },
44
45 /// On-disk schema is newer than this library build (upgrade rustbrain).
46 #[error("schema version mismatch: found {found}, supported {supported}")]
47 SchemaVersion {
48 /// Version found in `schema_meta`.
49 found: u32,
50 /// Maximum version this binary understands.
51 supported: u32,
52 },
53
54 /// CSR `graph.mmap` magic/version/bounds validation failure.
55 #[error("mmap format error: {0}")]
56 MmapFormat(String),
57
58 /// Empty or illegal full-text query after sanitization.
59 #[error("FTS query error: {0}")]
60 FtsQuery(String),
61
62 /// Called an API that requires a Cargo feature not enabled for this build.
63 #[error("feature not enabled: {0}")]
64 FeatureDisabled(&'static str),
65
66 /// Tree-sitter / AST extraction failure.
67 #[error("AST parse error: {0}")]
68 Ast(String),
69
70 /// Workspace walk / index pipeline failure.
71 #[error("indexer error: {0}")]
72 Indexer(String),
73
74 /// Portable `.brainbundle` export or import failure.
75 #[error("export/import error: {0}")]
76 Bundle(String),
77
78 /// Catch-all for rare internal conditions with a message.
79 #[error("{0}")]
80 Other(String),
81}
82
83impl BrainError {
84 /// Construct an [`BrainError::Other`] from any displayable message.
85 pub fn other(msg: impl Into<String>) -> Self {
86 Self::Other(msg.into())
87 }
88
89 /// Construct an [`BrainError::MmapFormat`] from any displayable message.
90 pub fn mmap(msg: impl Into<String>) -> Self {
91 Self::MmapFormat(msg.into())
92 }
93
94 /// Construct an [`BrainError::Indexer`] from any displayable message.
95 pub fn indexer(msg: impl Into<String>) -> Self {
96 Self::Indexer(msg.into())
97 }
98
99 /// Construct an [`BrainError::Bundle`] from any displayable message.
100 pub fn bundle(msg: impl Into<String>) -> Self {
101 Self::Bundle(msg.into())
102 }
103}
104
105/// Convenient result alias for library APIs: `Result<T, BrainError>`.
106pub type Result<T> = std::result::Result<T, BrainError>;