influxdata/influxdb · error · TableIndexCacheError

Failed to split persisted snapshot into table snapshots

Error message

Failed to split persisted snapshot into table snapshots

What it means

TableIndexCacheError::SplitPersistedSnapshotError, thrown when splitting a persisted wal/snapshot into per-table snapshots fails inside the TableIndex layer (wrapping crate::table_index::TableIndexError). The cache converts one catalog snapshot into multiple TableIndexSnapshot objects; a structural problem in the snapshot data aborts the load.

Solutions

  1. Inspect the inner TableIndexError (via #[source]) to find the specific snapshot field or entry that failed validation
  2. Restore from a consistent backup or an earlier valid snapshot; ensure restores copy the full snapshot set atomically
  3. Pin the reader to the same InfluxDB 3 version that wrote the snapshot, or upgrade to a version that reads the newer format
  4. Delete/rebuild the affected table index from the WAL/parquet data using the recovery tooling, since snapshots are derived state

Example fix

// before: hard fail the whole cache init
let per_table = split_persisted_snapshot(&snap)?;
// after: isolate the failure and fall back to reloading from source parquet
match split_persisted_snapshot(&snap) {
    Ok(per_table) => hydrate(per_table),
    Err(e) => { error!(error=?e, "snapshot split failed; rebuilding index"); rebuild_index_from_parquet(db_id, table_id).await?; }
}
Defensive patterns

Strategy: fallback

Validate before calling

// validate snapshot payload before split
fn snapshot_self_check(snap: &PersistedSnapshot) -> Result<(), String> {
    if snap.parquet_files.is_empty() { return Err("empty snapshot".into()); }
    if snap.min_sequence_number > snap.max_sequence_number {
        return Err("sequence range inverted".into());
    }
    Ok(())
}

Try / catch

match result {
    Err(TableIndexCacheError::SplitPersistedSnapshotError(e)) => {
        error!(source=?e, "snapshot split failed; falling back to full index rebuild");
        rebuild_from_parquet().await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Loading a TableIndex from the object store: the persisted snapshot (parquet file list, table mappings, sequence numbers) is split per table; TableIndex methods like split_persisted_snapshot return TableIndexError when entries reference missing tables, sequence gaps, or malformed snapshot payloads.

Common situations: Snapshot JSON corrupted or truncated by an interrupted write/crash; data written by a newer InfluxDB 3 version then read by an older one (schema drift); object store objects manually copied out of order during restore.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at influxdb3_write/src/table_index_cache.rs:93

    #[error("Failed to update table index: join task failed")]
    UpdateTaskFailed(#[source] tokio::task::JoinError),

    #[error("Failed to list object store metadata")]
    ListMetasError(#[source] object_store::Error),

    #[error("Failed to load table index conversion marker bytes from object store")]
    LoadConversionMarkerBytesError(#[source] object_store::Error),

    #[error("Failed to serialize initial table index conversion marker")]
    SerializeConversionMarkerError(#[source] serde_json::Error),

    #[error("Failed to put initial table index conversion marker to object store")]
    PutConversionMarkerError(#[source] object_store::Error),

    #[error("Failed to parse snapshot info file path")]
    ParseSnapshotPathError(#[source] anyhow::Error),

    #[error("Failed to split persisted snapshot into table snapshots")]
    SplitPersistedSnapshotError(#[source] crate::table_index::TableIndexError),

    #[error("Failed to load table index from object store")]
    LoadTableIndexFromObjectStoreError(#[source] crate::table_index::TableIndexError),

    #[error("Failed to update table index from object store")]
    UpdateTableIndexFromObjectStoreError(#[source] crate::table_index::TableIndexError),

    #[error("Failed to create table index from object store")]
    CreateTableIndexFromObjectStoreError(#[source] crate::table_index::TableIndexError),

    #[error("Failed to delete parquet file {path} from object store")]
    DeleteParquetFile {
        path: String,
        #[source]
        source: object_store::Error,
    },

View on GitHub (pinned to 06200ef96b)