pub enum StorageError {
Show 23 variants
NotFound {
capability: StorageCapability,
resource: &'static str,
key: String,
},
AlreadyExists {
capability: StorageCapability,
resource: &'static str,
key: String,
},
Conflict {
capability: StorageCapability,
operation: Cow<'static, str>,
message: String,
},
InvalidInput {
capability: StorageCapability,
operation: Cow<'static, str>,
message: String,
},
Unsupported {
capability: StorageCapability,
operation: Cow<'static, str>,
message: String,
},
BlobTooLarge {
content_ref: ContentRef,
max_bytes: u64,
observed_at_least: u64,
},
BlobSizeMismatch {
content_ref: ContentRef,
metadata_bytes: u64,
actual_bytes: u64,
},
BlobDigestMismatch {
expected: ContentRef,
actual: ContentRef,
},
Pool {
operation: Cow<'static, str>,
message: String,
},
Timeout {
operation: Cow<'static, str>,
},
AdmissionTimeout {
operation: Cow<'static, str>,
timeout_ms: u64,
},
Transaction {
operation: Cow<'static, str>,
message: String,
},
ReadTransactionAgeEvicted {
operation: Cow<'static, str>,
max_age_secs: u64,
},
ReadTransactionAgeEvictionCleanupFailed {
operation: Cow<'static, str>,
max_age_secs: u64,
message: String,
},
Serialization {
capability: StorageCapability,
message: String,
},
IndexMaintenance {
capability: StorageCapability,
message: String,
},
Driver {
capability: StorageCapability,
operation: Cow<'static, str>,
source: Box<dyn StdError + Send + Sync>,
},
WriteQueueFull {
timeout_ms: u64,
},
WriterTaskBusy {
timeout_ms: u64,
},
WriterTaskTerminated {
request_state: WriterTaskRequestState,
},
Internal(String),
WriterTaskNoRuntime,
CapacityFloor {
capability: StorageCapability,
volume: String,
available_bytes: u64,
floor_bytes: u64,
},
}Expand description
Unified error type for all storage operations.
Variants§
NotFound
AlreadyExists
Conflict
InvalidInput
Unsupported
BlobTooLarge
The authoritative object is larger than the caller’s declared
whole-buffer limit. observed_at_least is either opened-object
metadata used for early refusal or the running byte count that first
crossed the limit; metadata is not treated as the actual-byte bound.
BlobSizeMismatch
The complete bounded body disagreed with metadata obtained from the same opened object / GET response.
BlobDigestMismatch
The complete, size-consistent bounded body did not hash to the requested content-addressed reference.
Pool
Timeout
AdmissionTimeout
A bounded wait for storage admission (a reader/writer handle slot or a
pooled reader checkout) elapsed before anything was acquired. The
operation never started, so retrying cannot duplicate a side effect —
distinct from StorageError::Timeout, which makes no claim about
whether work was in flight when the deadline expired.
Fields
Transaction
ReadTransactionAgeEvicted
A cached read-only handle’s admitted transaction pinned a WAL
snapshot past the configured read_tx_max_age bound and was
proactively rolled back so the next call can open a fresh snapshot
(#1846). Distinct from the generic StorageError::Transaction
variant — which also covers failed-cleanup and write-side ambiguity
cases that are not uniformly safe to retry — so callers (and MCP
dispatch) can recognize this specific, always-safe-to-retry
condition by variant rather than by parsing rendered text.
ReadTransactionAgeEvictionCleanupFailed
A cached read-only handle’s admitted transaction pinned a WAL
snapshot past read_tx_max_age, and the proactive rollback used to
end the eviction (#1846) did not restore autocommit, or the rollback
itself failed. The connection is discarded either way rather than
returned to the pool. The age check that triggered this still ran
before any read on the connection, so — exactly like
StorageError::ReadTransactionAgeEvicted — retrying the caller’s
operation on a fresh connection is always safe; this variant exists
only to keep that guarantee distinguishable from a clean eviction in
the rendered message and to keep StorageError::Transaction (whose
other cases are not uniformly safe to retry) out of this path.
Serialization
IndexMaintenance
Driver
Fields
capability: StorageCapabilityWriteQueueFull
The bounded write-queue channel (ADR-067 Component A) did not free
capacity within the caller-supplied deadline. Returned only when a
caller wraps WriterTaskHandle::send’s channel.send().await in a
tokio::time::timeout; there is no immediate-error try_send path.
WriterTaskBusy
SQLite refused the writer task’s BEGIN IMMEDIATE with
SQLITE_BUSY/SQLITE_LOCKED until the configured busy timeout. The
queue accepted the request, but its operation closure was never
invoked, so retrying that one failed operation is safe.
WriterTaskTerminated
A single-writer execution seam has terminated permanently. This is the historical writer-task variant and display name; the fail-closed pool-mutex fallback also uses it when transaction finalization becomes terminal. The state identifies what is known about this request at that boundary. Retrying on the same pool cannot recover the retired writer seam.
Fields
request_state: WriterTaskRequestStateInternal(String)
An internal storage failure not attributable to a specific storage capability.
WriterTaskNoRuntime
KHIVE_WRITE_QUEUE=1 is set but the calling thread has no Tokio
runtime context, so the writer task cannot be spawned (ADR-067
Component A). Returned instead of panicking.
See crates/khive-storage/docs/api/error-taxonomy.md#writertasknoruntime.
CapacityFloor
A filesystem-backed capability (e.g. BlobStore) refused a write
because volume’s available space, after accounting for the pending
write, would drop below the configured free-space floor (khive#292).
Implementations§
Source§impl StorageError
impl StorageError
Sourcepub fn driver(
capability: StorageCapability,
operation: impl Into<Cow<'static, str>>,
source: impl StdError + Send + Sync + 'static,
) -> Self
pub fn driver( capability: StorageCapability, operation: impl Into<Cow<'static, str>>, source: impl StdError + Send + Sync + 'static, ) -> Self
Construct a Driver error wrapping a backend-specific error source.
Sourcepub fn capability(&self) -> Option<StorageCapability>
pub fn capability(&self) -> Option<StorageCapability>
Return the storage capability surface that produced this error, if any.
Sourcepub fn is_retryable(&self) -> bool
pub fn is_retryable(&self) -> bool
Whether this error is transient and the operation may succeed on retry.
Sourcepub fn is_fts5_syntax_error(&self) -> bool
pub fn is_fts5_syntax_error(&self) -> bool
Whether this error is an FTS5 query-parser rejection of the MATCH expression itself, as opposed to a connection/pool/driver-level failure of the text-search backend.
True only for Driver errors from the Text capability at the
fts_search operation whose message names one of SQLite’s FTS5
parser failure modes (syntax error, stack overflow, unsupported
column/phrase/NEAR query); all other errors return false.
Callers that fail-open the FTS leg of a hybrid search (degrading to
vector-only results on a bad query string) MUST gate on this
predicate rather than on StorageError broadly — treating every
Err as degradable turns a real backend outage into a silently-empty
“successful” search (issue #389).
See crates/khive-storage/docs/api/error-taxonomy.md#is_fts5_syntax_error.
Sourcepub fn is_unique_constraint_violation(&self) -> bool
pub fn is_unique_constraint_violation(&self) -> bool
Whether this error is a UNIQUE constraint violation from a raw SQL
execute (e.g. an INSERT racing an existing row under a natural
key). True only for Driver errors from the Sql capability whose
operation is one of execute, pool_writer.execute, or
tx.execute, and whose message contains UNIQUE constraint failed.
Batch/script operations are intentionally excluded.
Callers that treat exact-key duplicates as a tolerated no-op
(ADR-081 §4 serve-ledger idempotency) MUST gate on this predicate
rather than swallowing every Driver error at execute — that would
also hide genuine write failures (disk full, corruption).
See crates/khive-storage/docs/api/error-taxonomy.md#is_unique_constraint_violation.
Trait Implementations§
Source§impl Debug for StorageError
impl Debug for StorageError
Source§impl Display for StorageError
impl Display for StorageError
Source§impl Error for StorageError
impl Error for StorageError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()