chronix_engine/segment/error.rs
1//! Segment error types.
2
3use thiserror::Error;
4
5/// Errors that can occur during segment operations.
6#[derive(Debug, Error)]
7pub enum SegmentError {
8 /// The segment file is corrupt or has an invalid format.
9 #[error("corrupt segment file: {detail}")]
10 CorruptFile {
11 /// Human-readable description of the corruption.
12 detail: String,
13 },
14
15 /// Invalid magic bytes in header or footer.
16 #[error("invalid magic bytes: expected CXSG")]
17 InvalidMagic,
18
19 /// `CRC32c` checksum mismatch.
20 #[error("checksum mismatch: expected {expected:#010x}, got {actual:#010x}")]
21 ChecksumMismatch {
22 /// Expected checksum value.
23 expected: u32,
24 /// Actual computed checksum.
25 actual: u32,
26 },
27
28 /// The segment belongs to a different format generation.
29 ///
30 /// The message is built by [`crate::format::version_mismatch`], so every
31 /// durable format says the same thing in the same words — and names the
32 /// remedy rather than printing a bare number, which is what this used to
33 /// do.
34 #[error("{detail}")]
35 UnsupportedVersion {
36 /// The version number found in the file.
37 version: u16,
38 /// What was read, what this build expects, and what to do.
39 detail: String,
40 },
41
42 /// An I/O error occurred.
43 #[error("I/O error: {0}")]
44 Io(#[from] std::io::Error),
45
46 /// An encoding error occurred.
47 #[error("encoding error: {0}")]
48 Encoding(#[from] chronix_encoding::EncodingError),
49
50 /// The segment writer has already been finalized.
51 #[error("segment writer already finalized")]
52 AlreadyFinalized,
53
54 /// No data has been written to the segment.
55 #[error("no data written to segment")]
56 EmptySegment,
57
58 /// Row group index is out of range.
59 #[error("row group index {index} out of range (max: {max})")]
60 RowGroupOutOfRange {
61 /// Requested row group index.
62 index: usize,
63 /// Maximum valid row group index.
64 max: usize,
65 },
66
67 /// Column not found.
68 /// An encrypted column cannot be read because its key is not available.
69 ///
70 /// **Not** [`CorruptFile`](Self::CorruptFile), which is what this used to
71 /// be: nothing is wrong with the bytes. The deployment is missing a key,
72 /// and the two have completely different next steps — one is "restore
73 /// from a backup", the other is "set the environment variable". The
74 /// commonest way to arrive here is restoring an encrypted backup onto a
75 /// machine the key was never given to.
76 #[error(
77 "column '{column}' is encrypted with key '{key_id}', which this database has no \
78 key for — set it under [database.field_encryption] and restart"
79 )]
80 MissingEncryptionKey {
81 /// The column that cannot be read.
82 column: String,
83 /// The key id its blocks were written under.
84 key_id: String,
85 },
86
87 /// The writer was asked for something the format cannot honestly do.
88 ///
89 /// Distinct from [`CorruptFile`](Self::CorruptFile): nothing is wrong
90 /// with the data, the *configuration* is wrong — declaring a tag column
91 /// encrypted, for instance, which the format would accept and which
92 /// would publish the value in the sidecar beside it.
93 #[error("invalid segment writer configuration: {detail}")]
94 InvalidConfiguration {
95 /// What was asked for, and why it cannot be done.
96 detail: String,
97 },
98
99 /// A requested column is not in the segment.
100 #[error("column not found: {name}")]
101 ColumnNotFound {
102 /// The requested column name.
103 name: String,
104 },
105}
106
107/// A specialized `Result` type for segment operations.
108pub type Result<T> = std::result::Result<T, SegmentError>;