Skip to main content

Error

Enum Error 

Source
#[non_exhaustive]
pub enum Error {
Show 30 variants Io(Error), Decompress(CompressionType), InvalidVersion(u8), Unrecoverable, ChecksumMismatch { got: Checksum, expected: Checksum, }, MemtableKvChecksumMismatch { seqno: u64, got: u64, expected: u64, }, MemtableKvChecksumCorruptAlgorithm { seqno: u64, tag: u8, }, HeaderCrcMismatch { recomputed: u32, stored: u32, }, InvalidTag((&'static str, u8)), InvalidTrailer, InvalidHeader(&'static str), DecompressedSizeTooLarge { declared: u64, limit: u64, }, Utf8(Utf8Error), MergeOperator, Encrypt(&'static str), Decrypt(&'static str), ComparatorMismatch { stored: String, supplied: &'static str, }, ZstdDictMismatch { expected: u32, got: Option<u32>, }, ManifestFrameChecksumMismatch { section: &'static str, expected: u64, got: u64, }, RangeTombstoneDecode { field: &'static str, offset: u64, }, MixedOperationBatch, PageEccUnsupported, PageEccUnrecoverable { got: Checksum, expected: Checksum, }, RouteMismatch { expected: usize, found: usize, }, FeatureUnsupported(&'static str), Locked(String), ManifestFooterInvalid(&'static str), ManifestSectionInvalid(&'static str), TornManifestEditLog { kind: &'static str, }, StorageFull { used: u64, limit: u64, },
}
Expand description

Represents errors that can occur in the LSM-tree

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Io(Error)

I/O error

§

Decompress(CompressionType)

Decompression failed

§

InvalidVersion(u8)

Invalid or unparsable data format version

§

Unrecoverable

Some required files could not be recovered from disk

§

ChecksumMismatch

Checksum mismatch

Fields

§got: Checksum

Checksum of loaded block

§expected: Checksum

Checksum that was saved in block header

§

MemtableKvChecksumMismatch

A memtable entry’s per-KV digest, computed at insert under KvChecksumComputePoint::AtInsert, did not match a recompute over the entry’s current bytes at flush.

This is the memtable-residence RAM-corruption signal: the entry’s logical content (value_type, seqno, key, or value) changed while it sat in the memtable, between insert and flush. Distinct from Self::ChecksumMismatch (on-disk block bytes) — this catches a flip that happens entirely in RAM, before any block is written.

Fields

§seqno: u64

Sequence number of the entry whose digest diverged (locates it).

§got: u64

Digest recomputed over the entry’s current memtable bytes at flush.

§expected: u64

Digest computed and stored when the entry was inserted.

§

MemtableKvChecksumCorruptAlgorithm

A memtable entry carried an insert-time per-KV digest (KvChecksumComputePoint::AtInsert) tagged with an algorithm AtInsert never stores: a non-4-byte or unknown algorithm wire tag.

AtInsert only ever writes a 4-byte algorithm tag (Xxh3Low32 / Crc32c), so a digest-bearing node tagged otherwise means the node’s algorithm metadata was corrupted in RAM during memtable residence. Distinct from Self::MemtableKvChecksumMismatch (the digest value diverged): here the algorithm itself is unusable, so the engine refuses to “verify” the entry under the wrong algorithm rather than risk a flipped tag passing the residence check.

Fields

§seqno: u64

Sequence number of the entry whose algorithm tag is invalid.

§tag: u8

The invalid algorithm wire tag read from the node.

§

HeaderCrcMismatch

Blob frame header CRC mismatch (V4 format). Distinct from ChecksumMismatch which covers data payload checksums.

Fields

§recomputed: u32

CRC recomputed from header fields

§stored: u32

CRC stored in the blob frame header

§

InvalidTag((&'static str, u8))

Invalid enum tag

§

InvalidTrailer

Invalid block trailer

§

InvalidHeader(&'static str)

Invalid block header

§

DecompressedSizeTooLarge

Data size (decompressed, on-disk, or requested) is invalid or exceeds a safety limit

Fields

§declared: u64

Size associated with the data being processed. This may come from on-disk/in-memory metadata (e.g., header, block/value handle) or be derived from caller input (e.g., a requested key or value length), and may be zero, invalid, or over the configured limit.

§limit: u64

Maximum allowed size for the data or request being processed

§

Utf8(Utf8Error)

UTF-8 error

§

MergeOperator

Merge operator failed.

No context payload — consistent with other unit variants (Unrecoverable, InvalidTrailer). Operators should log details before returning this error.

§

Encrypt(&'static str)

Encryption failed

§

Decrypt(&'static str)

Decryption failed

§

ComparatorMismatch

Comparator mismatch on tree reopen.

The tree was created with a comparator whose crate::UserComparator::name differs from the one supplied at reopen time.

Fields

§stored: String

Comparator name persisted in the tree metadata.

§supplied: &'static str

Comparator name supplied by the caller.

§

ZstdDictMismatch

Zstd dictionary required but not provided, or dict_id mismatch

Fields

§expected: u32

Dictionary ID stored in the block/table metadata

§got: Option<u32>

Dictionary ID provided by the caller (None if no dictionary supplied)

§

ManifestFrameChecksumMismatch

Per-record XXH3-64 mismatch inside a framed manifest section (tables / blob_files). Distinct from Error::ChecksumMismatch — same XXH3 family but a different output width (XXH3-64 here vs XXH3-128 for block-level payloads) on a different layer of the on-disk format, with different recovery semantics (manifest framing surfaces routed through ManifestRecoveryMode; block checksums surface via Error::ChecksumMismatch for the block I/O paths). Strict manifest recovery modes surface this so an operator can see the exact 64-bit digests that disagreed; SkipAnyCorruptedRecords and PointInTimeRecovery route around the corruption without raising it.

Fields

§section: &'static str

SFA section the corrupt record was found in (e.g. "tables", "blob_files"). Static so this can be compared without parsing message strings.

§expected: u64

XXH3-64 digest the framing header claimed for the record’s payload.

§got: u64

XXH3-64 digest the reader recomputed over the bytes actually on disk.

§

RangeTombstoneDecode

Range tombstone block decode failure.

Fields

§field: &'static str

Which field or validation failed (e.g. start_len, start, seqno, interval)

§offset: u64

Byte offset within the block to the start of the field whose decoding failed (captured before reading bytes for that field).

§

MixedOperationBatch

A WriteBatch contains mixed operation types (e.g. insert + remove) for the same user key.

Mixed ops at the same logical version are rejected because the memtable/skiplist ordering ties on (user_key, seqno) and does not include value_type as a tie-breaker. That would otherwise make equal-key entries with different operation types ambiguous to later reads and merges, yielding tie-break-dependent “last write wins” semantics.

§

PageEccUnsupported

Tree was opened with Config::page_ecc(true) but this build of the crate does not have the page_ecc cargo feature enabled. The reader has no way to verify or recover Reed-Solomon parity without the codec, so opening such a tree would silently downgrade integrity guarantees — return this error instead.

§

PageEccUnrecoverable

Block payload failed the XXH3 integrity check and the attached Reed-Solomon parity trailer could not reconstruct it (more shards are corrupted than the (4, 2) RS scheme can recover). Surfaced ONLY by ECC-protected blocks (the ECC_PARITY header flag set); a block written without parity (Config::page_ecc(false)) on a checksum mismatch returns Self::ChecksumMismatch instead, because there’s no parity to even attempt recovery from.

Fields

§got: Checksum

XXH3 checksum recomputed from the on-disk bytes.

§expected: Checksum

XXH3 checksum stored in the block header.

§

RouteMismatch

Route-compatibility mismatch on reopen.

Recovery found fewer tables on disk than the manifest expects, and all missing tables are on levels not covered by any current level_routes. This typically means a previously configured route was removed, leaving its directory unreachable.

Re-adding the missing route(s) will usually resolve the error. If missing tables are on levels that are covered by a current route, recovery returns Unrecoverable instead (the SST files were genuinely lost).

Fields

§expected: usize

Number of tables listed in the manifest.

§found: usize

Number of tables actually found across all configured routes.

§

FeatureUnsupported(&'static str)

Valid configuration / on-disk layout that this build does not yet know how to process, or constructor input that violates a documented invariant (e.g. CompressionType::None passed to [crate::table::block::CompressionContext::new]). Distinct from Error::Unrecoverable (signals corruption) and from Error::Io with ErrorKind::Unsupported (which can also surface from platform / backend limits); the &'static str payload names the specific marker that triggered the rejection (e.g. "filter_tli" for a partitioned filter SFA section, "compression-context-none" for the constructor invariant) so the caller can route the diagnostic without parsing message strings.

§

Locked(String)

The tree directory is already locked by another live instance.

Returned by Config::open and Config::repair when the cross-process directory lock (a LOCK file under the tree directory, held via an advisory OS file lock) could not be acquired because another process owns it. Holds the directory path as a display string for diagnostics. Two processes mutating the same manifest would corrupt it, so the second acquirer fails fast here. Disable the lock with Config::with_directory_lock only when exclusivity is enforced at a higher layer.

§

ManifestFooterInvalid(&'static str)

Manifest footer / TOC / file-level discovery failure.

Scoped to errors detected at or before the TOC is parsed — i.e. everything the reader needs before it can answer “where is section X”. Section-content failures (a specific section’s Block fails verification) go through ManifestSectionInvalid instead so callers like Tree::open can distinguish a totally unreadable manifest from a per-section problem.

Typical causes:

  • Footer-payload structural failure: unknown layout version, oversized section count, empty/oversized section name, invalid UTF-8, duplicate section name, footer payload exceeds the 4 KiB reservation.
  • Tail / head-mirror double failure: both the tail-footer Block read and the head-mirror fallback failed verification (XXH3 mismatch, AEAD decryption, parse error). Per-path causes are logged at error level and collapsed here.
  • TOC entry value corruption: a TOC entry’s block_offset + block_size overflows u64 or extends past the end of the file. The TOC bytes are footer payload, so a malformed TOC entry is a footer-level issue even though it surfaces in ManifestArchiveReader::read_section.
  • Trailing size-hint corruption: the tail’s 4-byte footer-size hint is zero or exceeds HEAD_FOOTER_RESERVED_SIZE (4 KiB), or the implied section_end lands inside the head reservation. Caught in both the reader and checkpoint::write_current_for_version.
  • Writer-side invariant breach: write_cursor would overflow u64, an in-memory section would exceed the on-disk Block-size cap, etc.
  • CURRENT pointer points at a missing manifest: when version::get_current_version opens the referenced v{N} file and gets NotFound, the error is rewrapped here so Tree::open’s outer Io(NotFound) => create_new arm cannot mistake a half-applied recovery / corrupted state for a clean first-open.
§

ManifestSectionInvalid(&'static str)

Manifest section content failed verification or matched no TOC entry.

Surfaced by ManifestArchiveReader::read_section (and the helper that validates the inner Block header before delegating to Block::from_reader). Distinct from ManifestFooterInvalid because the footer / TOC loaded fine — the bad bytes are localised to one section Block and a caller MAY route recovery differently (e.g. skip the section vs. refuse the whole manifest).

Causes:

  • Requested section name not in TOC: the caller asked for a section that the manifest doesn’t declare.
  • Section Block header doesn’t fit its outer buffer: the inner block’s derived on-disk size (header + payload + parity-if-flagged) exceeds the TOC-declared block_size. Defence-in-depth against a forged TOC pointing at a too-small slot.
  • Block decoded at the TOC offset has the wrong block_type: TOC says “section here” but the bytes carry a non-Manifest Block. Defence-in-depth against TOC-redirect attacks; once AAD-binding lands in encryption::block, Block::from_reader will reject this internally and the check here becomes belt-and- braces.
§

TornManifestEditLog

The trailing record of the incremental manifest edit log is incomplete or corrupt, and the active ManifestRecoveryMode does not tolerate that defect, so the open aborts rather than silently rolling the edit back.

A clean end-of-log is never reported here: a crash exactly at a record boundary is byte-identical to a pristine close, so that case is always tolerated. This fires when bytes of a trailing record are present but the record fails framing — a power-loss-truncated append (only AbsoluteConsistency rejects it; other modes roll it back), or a fully-framed record whose checksum doesn’t match (bit-rot) / whose header is forged (rejected by both AbsoluteConsistency and TolerateCorruptedTailRecords, which salvages writer-incomplete tails only; rolled back under PointInTimeRecovery / SkipAnyCorruptedRecords).

Recover by truncating the torn tail: run Config::repair, which rebuilds a clean standalone snapshot (dropping the edit log), or re-open under a ManifestRecoveryMode that tolerates the defect to roll the trailing edit back.

Fields

§kind: &'static str

The trailing defect detected: "truncated" (partial record from a power-loss-interrupted append), "checksum-mismatch" (fully-framed record whose payload bit-rotted), "bad-header" (implausible framing length), or "len-mismatch" (record length disagrees with the expected fixed size). Static so callers can branch without parsing the message string.

§

StorageFull

A write was declined by the storage admission gate because accepting it could push the tree’s live footprint past its effective budget.

Only produced when storage_admission_check is enabled. The predicate is computed, not latched: raising storage_limit_bytes, freeing disk, or a compaction reclaiming space clears the read-only state on the next check with no restart. Internal flush / compaction are never gated (reserved headroom), so the engine can always reclaim space.

Fields

§used: u64

Live on-disk bytes at the time of the check.

§limit: u64

Effective byte budget that used (plus reserved headroom) exceeded.

Trait Implementations§

Source§

impl Debug for Error

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Error

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for Error

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

Returns the lower-level source of this error, if any. Read more
1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<Error> for Error

Source§

fn from(value: Error) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for Error

Available on crate feature std only.
Source§

fn from(value: Error) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl Freeze for Error

§

impl RefUnwindSafe for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl UnsafeUnpin for Error

§

impl UnwindSafe for Error

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V