Skip to main content

nodedb_wal/
error.rs

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