Skip to main content

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>;