Skip to main content

nap_core/
error.rs

1//! Error types for the Narrative Addressing Protocol.
2//!
3//! All NAP errors are surfaced through [`NapError`], which captures the exact
4//! failure domain (URI parsing, manifest I/O, VCS operations, resolution, etc.)
5//! with enough context for callers to produce actionable diagnostics.
6
7use thiserror::Error;
8
9/// Top-level error type for all NAP operations.
10#[derive(Error, Debug)]
11pub enum NapError {
12    // ── URI Errors ──────────────────────────────────────────────────────
13    #[error("invalid NAP URI '{uri}': {reason}")]
14    InvalidUri { uri: String, reason: String },
15
16    // ── Manifest Errors ─────────────────────────────────────────────────
17    #[error("manifest not found: {0}")]
18    ManifestNotFound(String),
19
20    #[error("manifest parse error for '{path}': {source}")]
21    ManifestParseError {
22        path: String,
23        source: serde_yaml::Error,
24    },
25
26    #[error("manifest validation error: {0}")]
27    ManifestValidationError(String),
28
29    #[error("manifest write error for '{path}': {source}")]
30    ManifestWriteError {
31        path: String,
32        source: std::io::Error,
33    },
34
35    // ── Query Errors ────────────────────────────────────────────────────
36    #[error("query path not found: '{path}' in manifest '{manifest_id}'")]
37    QueryPathNotFound { path: String, manifest_id: String },
38
39    #[error("invalid query path: '{0}'")]
40    InvalidQueryPath(String),
41
42    // ── Repository Errors ───────────────────────────────────────────────
43    #[error("repository not found at '{0}'")]
44    RepositoryNotFound(String),
45
46    #[error("repository already exists at '{0}'")]
47    RepositoryAlreadyExists(String),
48
49    // ── Entity Type Errors ─────────────────────────────────────────────
50    #[error("entity type not found: '{0}'")]
51    EntityTypeNotFound(String),
52
53    // ── VCS Errors ──────────────────────────────────────────────────────
54    #[error("VCS error: {0}")]
55    VcsError(String),
56
57    #[error("ref not found: '{0}'")]
58    RefNotFound(String),
59
60    // ── Content Addressing Errors ───────────────────────────────────────
61    #[error("content hash mismatch: expected {expected}, got {actual}")]
62    ContentHashMismatch { expected: String, actual: String },
63
64    // ── I/O ─────────────────────────────────────────────────────────────
65    #[error("I/O error: {0}")]
66    Io(#[from] std::io::Error),
67
68    // ── Merge Errors ────────────────────────────────────────────────────
69    #[error("merge conflict at '{path}': {details}")]
70    MergeConflict { path: String, details: String },
71
72    #[error("SDL parse error: {0}")]
73    SdlParseError(String),
74
75    #[error("SDL validation error: {reason}")]
76    SdlValidationError { reason: String },
77
78    #[error("merge strategy error at '{path}': {reason}")]
79    MergeStrategyError { path: String, reason: String },
80
81    #[error("merge validation error: {reason}")]
82    MergeValidationError { reason: String },
83
84    // ── Resolution Errors ───────────────────────────────────────────────
85    #[error("no branch or commit specified and no default_branch configured. ")]
86    NoDefaultBranch,
87
88    // ── Permission ──────────────────────────────────────────────────────
89    #[error("permission denied: {0}")]
90    PermissionDenied(String),
91
92    // ── gRPC ─────────────────────────────────────────────────────────────
93    #[error("gRPC error: {0}")]
94    GrpcError(String),
95
96    // ── Catch-all ───────────────────────────────────────────────────────
97    #[error("{0}")]
98    Other(String),
99}
100
101/// Result type alias using [`NapError`].
102pub type NapResult<T> = Result<T, NapError>;