Skip to main content

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>;