1use std::path::PathBuf;
5use thiserror::Error;
6
7#[derive(Debug, Error)]
8#[non_exhaustive]
9pub enum UniError {
10 #[error("Database not found: {path}")]
11 NotFound { path: PathBuf },
12
13 #[error("Schema error: {message}")]
14 Schema { message: String },
15
16 #[error("Parse error: {message}")]
17 Parse {
18 message: String,
19 position: Option<usize>,
20 line: Option<usize>,
21 column: Option<usize>,
22 context: Option<String>,
23 },
24
25 #[error("Query error: {message}")]
26 Query {
27 message: String,
28 query: Option<String>,
29 },
30
31 #[error("Transaction error: {message}")]
32 Transaction { message: String },
33
34 #[error("Transaction conflict: {message}")]
35 TransactionConflict { message: String },
36
37 #[error("Transaction already completed")]
38 TransactionAlreadyCompleted,
39
40 #[error("Operation '{operation}' not supported on read-only database")]
42 ReadOnly { operation: String },
43
44 #[error("Label '{label}' not found in schema")]
46 LabelNotFound { label: String },
47
48 #[error("Edge type '{edge_type}' not found in schema")]
50 EdgeTypeNotFound { edge_type: String },
51
52 #[error("Property '{property}' not found on {entity_type} with label '{label}'")]
54 PropertyNotFound {
55 property: String,
56 entity_type: String, label: String,
58 },
59
60 #[error("Index '{index}' not found")]
62 IndexNotFound { index: String },
63
64 #[error("Snapshot '{snapshot_id}' not found")]
66 SnapshotNotFound { snapshot_id: String },
67
68 #[error("Query exceeded memory limit of {limit_bytes} bytes")]
70 MemoryLimitExceeded { limit_bytes: usize },
71
72 #[error("Database is locked by another process")]
73 DatabaseLocked,
74
75 #[error("Operation timed out after {timeout_ms}ms")]
76 Timeout { timeout_ms: u64 },
77
78 #[error("Type error: expected {expected}, got {actual}")]
79 Type { expected: String, actual: String },
80
81 #[error("Constraint violation: {message}")]
82 Constraint { message: String },
83
84 #[error("Storage error: {message}")]
85 Storage {
86 message: String,
87 #[source]
88 source: Option<Box<dyn std::error::Error + Send + Sync>>,
89 },
90
91 #[error("IO error: {0}")]
92 Io(#[from] std::io::Error),
93
94 #[error("Internal error: {0}")]
95 Internal(#[from] anyhow::Error),
96
97 #[error("Invalid identifier '{name}': {reason}")]
98 InvalidIdentifier { name: String, reason: String },
99
100 #[error("Label '{label}' already exists")]
101 LabelAlreadyExists { label: String },
102
103 #[error("Edge type '{edge_type}' already exists")]
104 EdgeTypeAlreadyExists { edge_type: String },
105
106 #[error("Permission denied: {action}")]
107 PermissionDenied { action: String },
108
109 #[error("Argument '{arg}' is invalid: {message}")]
110 InvalidArgument { arg: String, message: String },
111
112 #[error("A write context is already active on session '{session_id}'")]
114 WriteContextAlreadyActive {
115 session_id: String,
116 hint: &'static str,
117 },
118
119 #[error("Transaction '{tx_id}' commit timed out")]
121 CommitTimeout { tx_id: String, hint: &'static str },
122
123 #[error("Transaction '{tx_id}' expired")]
125 TransactionExpired { tx_id: String, hint: &'static str },
126
127 #[error("Operation cancelled")]
129 Cancelled,
130
131 #[error("Derived facts are stale: version gap is {version_gap}")]
133 StaleDerivedFacts { version_gap: u64 },
134
135 #[error("Rule conflict: rule '{rule_name}' conflicts during promotion")]
137 RuleConflict { rule_name: String },
138
139 #[error("Hook rejected: {message}")]
141 HookRejected { message: String },
142}
143
144pub type Result<T> = std::result::Result<T, UniError>;