Skip to main content

mana_core/
error.rs

1use std::path::PathBuf;
2
3/// Typed error for mana-core's public API surface.
4///
5/// Callers can match on variants to handle specific failure modes
6/// (e.g., distinguishing "unit not found" from "file corrupt").
7/// Internal functions still use `anyhow` — this type lives at the API boundary.
8#[derive(Debug, thiserror::Error)]
9pub enum ManaError {
10    /// The requested unit ID does not exist.
11    #[error("Unit {id} not found")]
12    UnitNotFound { id: String },
13
14    /// The unit ID is syntactically invalid (empty, special chars, path traversal).
15    #[error("Invalid unit ID: {id} — {reason}")]
16    InvalidId { id: String, reason: String },
17
18    /// Adding a dependency would create a cycle in the graph.
19    #[error("Dependency cycle detected: {details}")]
20    CycleDetected { details: String },
21
22    /// The verify command failed or timed out.
23    #[error("Verify failed: {reason}")]
24    VerifyFailed { reason: String },
25
26    /// Problem reading or validating `config.yaml`.
27    #[error("Configuration error: {0}")]
28    ConfigError(String),
29
30    /// Problem building, loading, or saving the index.
31    #[error("Index error: {0}")]
32    IndexError(String),
33
34    /// Could not acquire the index lock (another process may hold it).
35    #[error("Lock conflict: {0}")]
36    LockConflict(String),
37
38    /// YAML/frontmatter deserialization failed.
39    #[error("Parse error in {path}: {reason}")]
40    ParseError { path: PathBuf, reason: String },
41
42    /// Filesystem I/O failure.
43    #[error(transparent)]
44    IoError(#[from] std::io::Error),
45
46    /// Catch-all for internal errors that don't fit a specific variant.
47    /// Preserves the original `anyhow::Error` for debugging.
48    #[error(transparent)]
49    Internal(#[from] anyhow::Error),
50}
51
52/// Convenience alias used throughout the public API.
53pub type ManaResult<T> = std::result::Result<T, ManaError>;