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