crabka_log/error.rs
1//! Errors returned by `Log` and `Segment`.
2
3use thiserror::Error;
4
5/// Errors returned by [`Log`](crate::Log) and [`Segment`](crate::Segment).
6#[derive(Debug, Error)]
7pub enum LogError {
8 /// An I/O operation against the filesystem failed.
9 #[error("I/O: {0}")]
10 Io(#[from] std::io::Error),
11
12 /// A partial batch was found at the tail of a `.log` file during
13 /// recovery — the trailing bytes will be truncated to the last
14 /// cleanly decoded batch.
15 #[error("partial batch at offset {file_offset} in segment {segment}: truncating")]
16 PartialBatch {
17 /// Absolute base offset of the segment containing the partial batch.
18 segment: i64,
19 /// Byte position within the `.log` file where the partial batch starts.
20 file_offset: u64,
21 },
22
23 /// A batch's stored CRC did not match the one computed over its bytes.
24 #[error(
25 "CRC mismatch at offset {file_offset} in segment {segment}: \
26 expected {expected:#x}, computed {computed:#x}"
27 )]
28 CrcMismatch {
29 /// Absolute base offset of the segment.
30 segment: i64,
31 /// Byte position within the `.log` file where the corrupt batch starts.
32 file_offset: u64,
33 /// CRC value embedded in the batch header.
34 expected: u32,
35 /// CRC value re-computed by the reader.
36 computed: u32,
37 },
38
39 /// A caller requested an offset below [`Log::log_start_offset`](crate::Log::log_start_offset).
40 #[error("offset {requested} below log start {log_start}")]
41 OffsetTooLow {
42 /// Offset the caller asked for.
43 requested: i64,
44 /// Current log start.
45 log_start: i64,
46 },
47
48 /// Encoding/decoding of a `RecordBatch` failed.
49 #[error("records: {0}")]
50 Records(#[from] crabka_protocol::records::RecordsError),
51
52 /// A segment filename couldn't be parsed (e.g., wrong length, not all digits).
53 #[error("invalid segment filename: {0}")]
54 BadSegmentName(String),
55
56 /// A caller supplied an explicit offset to [`Log::append_at`](crate::Log::append_at)
57 /// that did not match the log's current end offset. Replication paths use
58 /// this to detect divergence between leader-assigned offsets and the local
59 /// log's expected next offset.
60 #[error("offset mismatch: expected {expected}, got {actual}")]
61 OffsetMismatch {
62 /// The offset the log expected — i.e. its current end offset.
63 expected: i64,
64 /// The offset the caller actually supplied.
65 actual: i64,
66 },
67
68 /// A log file (e.g., `.txnindex`) is corrupt: wrong size, bad checksum, etc.
69 #[error("corrupt log: {0}")]
70 Corrupt(String),
71
72 /// A caller supplied an invalid argument.
73 #[error("invalid argument: {0}")]
74 InvalidArgument(String),
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use assert2::assert;
81
82 #[test]
83 fn display_partial_batch() {
84 let e = LogError::PartialBatch {
85 segment: 0,
86 file_offset: 1024,
87 };
88 assert!(e.to_string().contains("offset 1024"));
89 assert!(e.to_string().contains("segment 0"));
90 }
91}