Skip to main content

nodedb_wal/
error.rs

1// SPDX-License-Identifier: Apache-2.0
2
3/// Errors produced by the WAL subsystem.
4#[derive(Debug, thiserror::Error)]
5pub enum WalError {
6    /// I/O error from the underlying file operations.
7    #[error("WAL I/O error: {0}")]
8    Io(#[from] std::io::Error),
9
10    /// CRC32C checksum mismatch during read/replay.
11    #[error("WAL checksum mismatch at LSN {lsn}: expected {expected:#010x}, got {actual:#010x}")]
12    ChecksumMismatch {
13        lsn: u64,
14        expected: u32,
15        actual: u32,
16    },
17
18    /// Checkpoint frame is corrupt: bad version, truncated payload, or CRC mismatch.
19    #[error("checkpoint frame corrupt at {path}: {detail}")]
20    CheckpointCorrupt { path: String, detail: String },
21
22    /// Record header has an invalid magic number — file is corrupted or not a WAL.
23    #[error("invalid WAL magic at offset {offset}: expected {expected:#010x}, got {actual:#010x}")]
24    InvalidMagic {
25        offset: u64,
26        expected: u32,
27        actual: u32,
28    },
29
30    /// WAL format version is not supported by this binary.
31    #[error("unsupported WAL format version {version} (supported: {supported})")]
32    UnsupportedVersion { version: u16, supported: u16 },
33
34    /// Unknown required record type encountered during replay.
35    /// Optional unknown record types are safely skipped.
36    #[error("unknown required record type {record_type} at LSN {lsn}")]
37    UnknownRequiredRecordType { record_type: u32, lsn: u64 },
38
39    /// Write payload exceeds maximum record size.
40    #[error("payload too large: {size} bytes (max: {max})")]
41    PayloadTooLarge { size: usize, max: usize },
42
43    /// Attempted to write to a WAL that has been closed or is in error state.
44    #[error("WAL is sealed and no longer accepting writes")]
45    Sealed,
46
47    /// Alignment violation — O_DIRECT requires aligned buffers and offsets.
48    #[error("alignment violation: {context} (required: {required}, actual: {actual})")]
49    AlignmentViolation {
50        context: &'static str,
51        required: usize,
52        actual: usize,
53    },
54
55    /// A mutex was poisoned (another thread panicked while holding the lock).
56    #[error("WAL lock poisoned: {context}")]
57    LockPoisoned { context: &'static str },
58
59    /// Encryption or decryption failed.
60    #[error("WAL encryption error: {detail}")]
61    EncryptionError { detail: String },
62
63    /// `DoubleWriteBuffer::open` was called with `DwbMode::Off`. Callers
64    /// that want the DWB disabled must not call `open` at all.
65    #[error("DoubleWriteBuffer::open called with DwbMode::Off")]
66    DwbOffNotOpenable,
67
68    /// Record payload failed structural validation (truncation, bad length
69    /// prefix, invalid UTF-8, etc.). Distinct from [`WalError::ChecksumMismatch`]
70    /// — the bytes passed CRC but the payload's own framing is wrong.
71    #[error("corrupt WAL record at LSN {lsn}: {detail}")]
72    CorruptRecord { lsn: u64, detail: String },
73
74    /// Record payload is structurally invalid at parse time, before the
75    /// surrounding LSN context is known (e.g., anchor payload decoded from
76    /// a byte slice during unit-level use).
77    #[error("invalid WAL payload: {detail}")]
78    InvalidPayload { detail: String },
79
80    /// Operation is not supported on the current platform (e.g. wasm32).
81    #[error("WAL operation not supported on this platform: {detail}")]
82    Unsupported { detail: &'static str },
83}
84
85pub type Result<T> = std::result::Result<T, WalError>;