influxdata/influxdb · error · TableIndexCacheError

TableIndex operation failed

Error message

TableIndex operation failed

What it means

TableIndexCacheError::TableIndex wraps a crate::table_index::TableIndexError raised while cache-driven operations load, update, create, or split table indexes. It is a pass-through wrapper: the cache delegated work to TableIndexSnapshot/CoreTableIndex and that layer failed, so fix the inner TableIndexError.

Solutions

  1. Unwrap the #[source] TableIndexError and handle its specific variant (ObjectStore, Json, MergeMismatch, etc.) — this variant is only a wrapper.
  2. If the inner error is ObjectStore/Json, follow those remediation steps (credentials/network or file corruption).
  3. If MergeMismatch, check for concurrent writers using the same node identifier prefix and ensure each node has a unique prefix.
  4. Re-run TableIndexCache::initialize after fixing the root cause to rebuild consistent in-memory state.

Example fix

// before: treating wrapper generically
Err(TableIndexCacheError::TableIndex(e)) => return Err(e.into()),
// after: match the inner cause
Err(TableIndexCacheError::TableIndex(TableIndexError::ObjectStore(oe))) => {
    warn!("transient store error, retrying: {oe}");
    retry().await
}
Defensive patterns

Strategy: try-catch

Type guard

fn inner_index_error(e: &TableIndexCacheError) -> Option<&TableIndexError> {
    match e {
        TableIndexCacheError::TableIndex(inner)
        | TableIndexCacheError::LoadTableIndexFromObjectStoreError(inner)
        | TableIndexCacheError::UpdateTableIndexFromObjectStoreError(inner)
        | TableIndexCacheError::CreateTableIndexFromObjectStoreError(inner) => Some(inner),
        _ => None,
    }
}

Try / catch

match cache.get_or_load(&id).await {
    Err(e) if inner_index_error(&e).is_some() => {
        handle_inner(inner_index_error(&e).unwrap());
    }
    other => other?,
}

Prevention

When it happens

Trigger: TableIndexCache::get_or_load (LoadTableIndexFromObjectStoreError path), update_from_object_store (UpdateTableIndexFromObjectStoreError / CreateTableIndexFromObjectStoreError), and snapshot splitting via TableIndexSnapshot::load_split_persist all surface inner TableIndexErrors through this variant.

Common situations: An index snapshot file is corrupt (inner Json), the object store blipped during load (inner ObjectStore), merge mismatches after concurrent updates, or a node ID prefix mismatch making the loaded index belong to another table.

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/918da7fac8ad21fb. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_write/src/table_index_cache.rs:48

    ParquetFile,
    paths::{
        SnapshotInfoFilePath, TableIndexConversionCompletedPath, TableIndexPath,
        TableIndexSnapshotPath,
    },
    table_index::{CoreTableIndex, IndexMetadata, TableIndex, TableIndexSnapshot},
};

use thiserror::Error;

#[derive(Debug, Error)]
pub enum TableIndexCacheError {
    #[error("Object store operation failed")]
    ObjectStore(#[source] object_store::Error),

    #[error("JSON serialization/deserialization failed")]
    Json(#[source] serde_json::Error),

    #[error("TableIndex operation failed")]
    TableIndex(#[source] crate::table_index::TableIndexError),

    #[error("Object meta is missing filename")]
    MissingFilename,

    #[error("Failed to parse snapshot sequence number from filename")]
    InvalidSnapshotSequenceNumber,

    #[error("Unexpected error")]
    Unexpected(#[source] anyhow::Error),

    #[error("Table snapshot persistence task failed")]
    TableSnapshotPersistenceTaskFailed(#[source] tokio::task::JoinError),

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

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

View on GitHub (pinned to 06200ef96b)