influxdata/influxdb · error · TableIndexError

Failed to load table index snapshot from object store

Error message

Failed to load table index snapshot from object store

What it means

TableIndexError::LoadSnapshot wraps an object_store::Error returned when fetching (GET) a single table index snapshot object fails. While replaying a table's snapshot history, each snapshot object is fetched from its TableIndexSnapshotPath; a failed GET (NotFound, network, auth, throttling) is wrapped here with the source error attached.

Solutions

  1. Check #[source] object_store::Error: if NotFound, the snapshot object is missing — repair or rebuild the index without it
  2. Verify object-store credentials allow GET on the snapshot prefix
  3. Check bucket lifecycle/expiration rules are not deleting snapshot objects prematurely
  4. Retry with backoff for transient network/5xx errors; then fall back to rebuilding the index from persisted parquet snapshots

Example fix

// before: lifecycle rule deleting snapshot objects after 1 day
{"Rules":[{"Prefix":"snapshots/","Expiration":{"Days":1}}]}
// after: keep snapshots at least as long as retention requires
{"Rules":[{"Prefix":"snapshots/","Expiration":{"Days":30}}]}
Defensive patterns

Strategy: retry

Validate before calling

// ensure referenced snapshots exist before replay
for snap in index.snapshots() {
    client.head(&snap.path()).await?; // NotFound here means repair needed
}

Type guard

fn is_load_snapshot(e: &TableIndexError) -> bool {
    matches!(e, TableIndexError::LoadSnapshot(_))
}

Try / catch

match load_snapshot(path).await {
    Err(e) if is_load_snapshot(&e) => {
        if source_is_not_found(&e) { rebuild_index_without(path).await?; }
        else { retry_with_backoff(load_snapshot(path), 3).await?; }
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling the snapshot replay path that does a get(...).bytes() on a snapshot object and maps Err(e) => TableIndexError::LoadSnapshot(e) (table_index.rs:436); also the direct bytes() read failure on the fetched request result.

Common situations: A snapshot referenced by the index was manually deleted or expired by a lifecycle policy; S3 eventual consistency/cross-region replication lag; credentials can list but not GET objects.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/0916c255c00b241f. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_write/src/table_index.rs:37

#[derive(Debug, Error)]
pub enum TableIndexError {
    #[error("Failed to load table index from object store")]
    LoadIndex(#[source] object_store::Error),

    #[error("Failed to deserialize table index")]
    SerializeIndex(#[source] serde_json::Error),

    #[error("Failed to deserialize table index")]
    DeserializeIndex(#[source] serde_json::Error),

    #[error("Failed to list table index snapshots from object store")]
    ListSnapshots(#[source] object_store::Error),

    #[error("Failed to list table indices from object store")]
    ListIndices(#[source] object_store::Error),

    #[error("Failed to load table index snapshot from object store")]
    LoadSnapshot(#[source] object_store::Error),

    #[error("Failed to deserialize table index snapshot")]
    DeserializeSnapshot(#[source] serde_json::Error),

    #[error("Failed to persist table index to object store")]
    PersistIndex(#[source] object_store::Error),

    #[error("Failed to delete table index snapshot from object store")]
    DeleteSnapshot(#[source] object_store::Error),

    #[error("Cannot merge table indices with mismatched identifiers: {expected} != {actual}")]
    MergeMismatch {
        expected: TableIndexId,
        actual: TableIndexId,
    },

    #[error("Failed to parse table index path from object store path")]

View on GitHub (pinned to 06200ef96b)