laminar_core/error_codes/mod.rs
1//! LaminarDB structured error code registry.
2//!
3//! Every error in LaminarDB carries a stable `LDB-NNNN` code that is:
4//! - Present in the error message (grep-able in logs)
5//! - Present in the source code (grep-able in code)
6//! - Stable across versions (codes are never reused)
7//!
8//! # Code Ranges
9//!
10//! | Range | Category |
11//! |-------|----------|
12//! | `LDB-0xxx` | General / configuration |
13//! | `LDB-1xxx` | SQL parsing & validation |
14//! | `LDB-2xxx` | Window / watermark operations |
15//! | `LDB-3xxx` | Join operations |
16//! | `LDB-4xxx` | Serialization / state |
17//! | `LDB-5xxx` | Connector / I/O |
18//! | `LDB-6xxx` | Checkpoint / recovery |
19//! | `LDB-7xxx` | DataFusion / Arrow interop |
20//! | `LDB-8xxx` | Internal / should-not-happen |
21//!
22//! This module is the canonical registry for all error code ranges.
23//! Downstream crates (`laminar-sql`, `laminar-db`, etc.) re-export from here.
24
25// ── General / Configuration (LDB-0xxx) ──
26
27/// Invalid configuration value.
28pub const INVALID_CONFIG: &str = "LDB-0001";
29/// Missing required configuration key.
30pub const MISSING_CONFIG: &str = "LDB-0002";
31/// Unresolved config variable (e.g. `${VAR}` placeholder).
32pub const UNRESOLVED_CONFIG_VAR: &str = "LDB-0003";
33/// Database is shut down.
34pub const SHUTDOWN: &str = "LDB-0004";
35/// Invalid operation for the current state.
36pub const INVALID_OPERATION: &str = "LDB-0005";
37/// Schema mismatch between Rust type and SQL definition.
38pub const SCHEMA_MISMATCH: &str = "LDB-0006";
39
40// ── SQL Parsing & Validation (LDB-1xxx) ──
41
42/// Unsupported SQL syntax.
43pub const SQL_UNSUPPORTED: &str = "LDB-1001";
44/// Query planning failed.
45pub const SQL_PLANNING_FAILED: &str = "LDB-1002";
46/// Column not found.
47pub const SQL_COLUMN_NOT_FOUND: &str = "LDB-1100";
48/// Table or source not found.
49pub const SQL_TABLE_NOT_FOUND: &str = "LDB-1101";
50/// Type mismatch.
51pub const SQL_TYPE_MISMATCH: &str = "LDB-1200";
52
53// ── Window / Watermark (LDB-2xxx) ──
54
55/// Watermark required for this operation.
56pub const WATERMARK_REQUIRED: &str = "LDB-2001";
57/// Invalid window specification.
58pub const WINDOW_INVALID: &str = "LDB-2002";
59/// Window size must be positive.
60pub const WINDOW_SIZE_INVALID: &str = "LDB-2003";
61/// Late data rejected by window policy.
62pub const LATE_DATA_REJECTED: &str = "LDB-2004";
63
64// ── Join (LDB-3xxx) ──
65
66/// Join key column not found or invalid.
67pub const JOIN_KEY_MISSING: &str = "LDB-3001";
68/// Time bound required for stream-stream join.
69pub const JOIN_TIME_BOUND_MISSING: &str = "LDB-3002";
70/// Temporal join requires a primary key on the right-side table.
71pub const TEMPORAL_JOIN_NO_PK: &str = "LDB-3003";
72/// Unsupported join type for streaming queries.
73pub const JOIN_TYPE_UNSUPPORTED: &str = "LDB-3004";
74// ── Serialization / State (LDB-4xxx) ──
75
76/// State serialization failed for an operator.
77pub const SERIALIZATION_FAILED: &str = "LDB-4001";
78/// State deserialization failed for an operator.
79pub const DESERIALIZATION_FAILED: &str = "LDB-4002";
80/// JSON parse error (connector config, CDC payload, etc.).
81pub const JSON_PARSE_ERROR: &str = "LDB-4003";
82/// Base64 decode error (inline checkpoint state).
83pub const BASE64_DECODE_ERROR: &str = "LDB-4004";
84/// State store key not found.
85pub const STATE_KEY_MISSING: &str = "LDB-4005";
86/// State corruption detected (checksum mismatch, invalid data).
87pub const STATE_CORRUPTION: &str = "LDB-4006";
88/// A cluster query shape has no vnode-keyed checkpoint and rebalance lifecycle.
89pub const CLUSTER_STATE_LIFECYCLE_UNSUPPORTED: &str = "LDB-4007";
90/// Managed operator state exceeded the configured pipeline working-state budget.
91pub const MANAGED_STATE_BUDGET_EXCEEDED: &str = "LDB-4008";
92// ── Connector / I/O (LDB-5xxx) ──
93
94/// Connector failed to establish a connection.
95pub const CONNECTOR_CONNECTION_FAILED: &str = "LDB-5001";
96/// Connector authentication failed.
97pub const CONNECTOR_AUTH_FAILED: &str = "LDB-5002";
98/// Connector read error.
99pub const CONNECTOR_READ_ERROR: &str = "LDB-5003";
100/// Connector write error.
101pub const CONNECTOR_WRITE_ERROR: &str = "LDB-5004";
102/// Connector configuration error.
103pub const CONNECTOR_CONFIG_ERROR: &str = "LDB-5005";
104/// Source not found.
105pub const SOURCE_NOT_FOUND: &str = "LDB-5010";
106/// Sink not found.
107pub const SINK_NOT_FOUND: &str = "LDB-5011";
108/// Source already exists.
109pub const SOURCE_ALREADY_EXISTS: &str = "LDB-5012";
110/// Sink already exists.
111pub const SINK_ALREADY_EXISTS: &str = "LDB-5013";
112/// Connector serde (serialization/deserialization) error.
113pub const CONNECTOR_SERDE_ERROR: &str = "LDB-5020";
114/// Schema inference or compatibility error.
115pub const CONNECTOR_SCHEMA_ERROR: &str = "LDB-5021";
116/// Exactly-once requires all sources to support replay.
117pub const EXACTLY_ONCE_NON_REPLAYABLE: &str = "LDB-5030";
118/// Exactly-once requires all sinks to support exactly-once semantics.
119pub const EXACTLY_ONCE_SINK_UNSUPPORTED: &str = "LDB-5031";
120/// Exactly-once requires checkpointing to be enabled.
121pub const EXACTLY_ONCE_NO_CHECKPOINT: &str = "LDB-5032";
122/// Mixed delivery capabilities — some sources are non-replayable.
123pub const MIXED_DELIVERY_CAPABILITIES: &str = "LDB-5033";
124/// A source requires checkpointing to release upstream progress or resources.
125pub const SOURCE_CHECKPOINT_REQUIRED: &str = "LDB-5034";
126/// The configured exactly-once source/sink protocol is incomplete.
127pub const EXACTLY_ONCE_PROTOCOL_INCOMPLETE: &str = "LDB-5035";
128/// Delivery requires a stronger state/checkpoint durability scope.
129pub const DELIVERY_STATE_DURABILITY_MISMATCH: &str = "LDB-5036";
130/// A replayable source has not passed production exactly-once certification.
131pub const EXACTLY_ONCE_SOURCE_UNCERTIFIED: &str = "LDB-5037";
132/// A keyed-upsert source has no declared relational key.
133pub const SOURCE_PRIMARY_KEY_REQUIRED: &str = "LDB-5038";
134/// A mutation source cannot yet enter the canonical changelog path.
135pub const SOURCE_MUTATION_NOT_ADMITTED: &str = "LDB-5039";
136
137// ── Checkpoint / Recovery (LDB-6xxx) ──
138
139/// Checkpoint creation failed.
140pub const CHECKPOINT_FAILED: &str = "LDB-6001";
141/// Checkpoint not found.
142pub const CHECKPOINT_NOT_FOUND: &str = "LDB-6002";
143/// Checkpoint recovery failed.
144pub const RECOVERY_FAILED: &str = "LDB-6003";
145/// Sink rollback failed during checkpoint abort.
146pub const SINK_ROLLBACK_FAILED: &str = "LDB-6004";
147/// WAL (write-ahead log) error.
148pub const WAL_ERROR: &str = "LDB-6005";
149/// WAL entry has invalid length (possible corruption).
150pub const WAL_INVALID_LENGTH: &str = "LDB-6006";
151/// WAL checksum mismatch.
152pub const WAL_CHECKSUM_MISMATCH: &str = "LDB-6007";
153/// Checkpoint manifest persistence failed.
154pub const MANIFEST_PERSIST_FAILED: &str = "LDB-6008";
155/// Checkpoint prune (old checkpoint cleanup) failed.
156pub const CHECKPOINT_PRUNE_FAILED: &str = "LDB-6009";
157/// Source offset metadata missing during recovery.
158pub const OFFSET_METADATA_MISSING: &str = "LDB-6011";
159/// The final operator has no planner-certified subscription distribution.
160pub const SUBSCRIPTION_PLAN_UNSUPPORTED: &str = "LDB-6020";
161/// Subscription history belongs to another stream incarnation.
162pub const SUBSCRIPTION_GENERATION_MISMATCH: &str = "LDB-6021";
163/// Requested subscription checkpoint has not committed.
164pub const SUBSCRIPTION_EPOCH_NOT_COMMITTED: &str = "LDB-6022";
165/// Requested subscription checkpoint is older than retained history.
166pub const SUBSCRIPTION_REPLAY_PRUNED: &str = "LDB-6023";
167/// Authoritative subscription manifest failed validation.
168pub const SUBSCRIPTION_MANIFEST_CORRUPT: &str = "LDB-6024";
169/// A committed subscription segment is unavailable.
170pub const SUBSCRIPTION_SEGMENT_MISSING: &str = "LDB-6025";
171/// A committed subscription segment failed integrity validation.
172pub const SUBSCRIPTION_SEGMENT_CORRUPT: &str = "LDB-6026";
173/// Subscription output schema differs from its durable certificate.
174pub const SUBSCRIPTION_SCHEMA_MISMATCH: &str = "LDB-6027";
175/// A committed partition sequence has a gap.
176pub const SUBSCRIPTION_SEQUENCE_GAP: &str = "LDB-6028";
177/// One frame identity names conflicting immutable content.
178pub const SUBSCRIPTION_CONFLICTING_DUPLICATE: &str = "LDB-6029";
179/// An output writer no longer owns its certified partition.
180pub const SUBSCRIPTION_STALE_WRITER: &str = "LDB-6030";
181/// Assignment authority changed during a subscription operation.
182pub const SUBSCRIPTION_ASSIGNMENT_CHANGED: &str = "LDB-6031";
183/// The committed subscription backend is unavailable.
184pub const SUBSCRIPTION_BACKEND_UNAVAILABLE: &str = "LDB-6032";
185/// A bounded subscriber queue was overrun.
186pub const SUBSCRIPTION_LAGGED: &str = "LDB-6033";
187/// A subscription resume token is malformed or fails authentication.
188pub const SUBSCRIPTION_RESUME_TOKEN_INVALID: &str = "LDB-6034";
189/// A subscription resume token has expired.
190pub const SUBSCRIPTION_RESUME_TOKEN_EXPIRED: &str = "LDB-6035";
191/// Required committed history disappeared outside the retention contract.
192pub const SUBSCRIPTION_RETENTION_LOST: &str = "LDB-6036";
193/// Subscription wire or segment protocol is unsupported.
194pub const SUBSCRIPTION_PROTOCOL_UNSUPPORTED: &str = "LDB-6037";
195
196// ── DataFusion / Arrow Interop (LDB-7xxx) ──
197
198/// Query execution failed (`DataFusion` engine error).
199/// Note: the SQL layer uses `LDB-9001` for execution failures visible to users;
200/// `LDB-7001` is for internal `DataFusion` interop issues.
201pub const QUERY_EXECUTION_FAILED: &str = "LDB-7001";
202/// Arrow schema or record batch error.
203pub const ARROW_ERROR: &str = "LDB-7002";
204/// `DataFusion` plan optimization failed.
205pub const PLAN_OPTIMIZATION_FAILED: &str = "LDB-7003";
206
207// ── Internal / Should-Not-Happen (LDB-8xxx) ──
208
209/// Internal error — this is a bug.
210pub const INTERNAL: &str = "LDB-8001";
211/// Pipeline error (start/shutdown lifecycle).
212pub const PIPELINE_ERROR: &str = "LDB-8002";
213/// Materialized view error.
214pub const MATERIALIZED_VIEW_ERROR: &str = "LDB-8003";
215/// Query pipeline error (stream execution context).
216pub const QUERY_PIPELINE_ERROR: &str = "LDB-8004";
217/// No compiled projection or cached plan for pre-aggregation query.
218pub const NO_COMPILED_PROJECTION: &str = "LDB-8050";
219
220// ── Ring 0 Hot Path Errors ──
221
222/// Ring 0 error — no heap allocation, no formatting on construction.
223///
224/// Only formatted when actually displayed (which happens outside Ring 0).
225/// Uses `Copy` and `repr(u16)` for zero-cost error reporting via counters.
226#[derive(Debug, Clone, Copy, PartialEq, Eq)]
227#[repr(u16)]
228pub enum HotPathError {
229 /// Event arrived after watermark — dropped.
230 LateEvent = 0x0001,
231 /// State store key not found.
232 StateKeyMissing = 0x0002,
233 /// Downstream backpressure — event buffered.
234 Backpressure = 0x0003,
235 /// Serialization buffer overflow.
236 SerializationOverflow = 0x0004,
237 /// Record batch schema does not match expected.
238 SchemaMismatch = 0x0005,
239 /// Aggregate state corruption detected.
240 AggregateStateCorruption = 0x0006,
241 /// Queue is full — cannot push event.
242 QueueFull = 0x0007,
243 /// Channel is closed/disconnected.
244 ChannelClosed = 0x0008,
245}
246
247impl HotPathError {
248 /// Returns a static error message. Cost: one match. No allocation.
249 #[must_use]
250 pub const fn message(self) -> &'static str {
251 match self {
252 Self::LateEvent => "Event arrived after watermark; dropped",
253 Self::StateKeyMissing => "State key not found in store",
254 Self::Backpressure => "Downstream backpressure; event buffered",
255 Self::SerializationOverflow => "Serialization buffer capacity exceeded",
256 Self::SchemaMismatch => "Record batch schema does not match expected",
257 Self::AggregateStateCorruption => "Aggregate state checksum mismatch detected",
258 Self::QueueFull => "Queue is full; cannot push event",
259 Self::ChannelClosed => "Channel is closed or disconnected",
260 }
261 }
262
263 /// Numeric code for metrics counters. Zero-cost.
264 #[must_use]
265 pub const fn code(self) -> u16 {
266 self as u16
267 }
268
269 /// Returns the `LDB-NNNN` error code string for this hot path error.
270 #[must_use]
271 pub const fn ldb_code(self) -> &'static str {
272 match self {
273 Self::LateEvent => LATE_DATA_REJECTED,
274 Self::StateKeyMissing => STATE_KEY_MISSING,
275 Self::Backpressure => "LDB-8010",
276 Self::SerializationOverflow => SERIALIZATION_FAILED,
277 Self::SchemaMismatch => SCHEMA_MISMATCH,
278 Self::AggregateStateCorruption => STATE_CORRUPTION,
279 Self::QueueFull => "LDB-8011",
280 Self::ChannelClosed => "LDB-8012",
281 }
282 }
283}
284
285impl std::fmt::Display for HotPathError {
286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287 write!(f, "[{}] {}", self.ldb_code(), self.message())
288 }
289}
290
291impl std::error::Error for HotPathError {}
292
293#[cfg(test)]
294mod tests;
295
296/// Severity level for warnings (schema inference, recovery, etc.).
297#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
298pub enum WarningSeverity {
299 /// Informational — operation succeeded but with caveats.
300 Info,
301 /// Warning — result may be inaccurate or degraded.
302 Warning,
303 /// Error — operation for this item failed; a fallback was used.
304 Error,
305}