{"record":{"id":"1b136283e0f3c51f","repo":"influxdata/influxdb","slug":"unexpected-error-table-index-cache","errorCode":null,"errorMessage":"Unexpected error","messagePattern":"Unexpected error","errorType":"exception","errorClass":"TableIndexCacheError","httpStatus":null,"severity":"error","filePath":"influxdb3_write/src/table_index_cache.rs","lineNumber":57,"sourceCode":"\n#[derive(Debug, Error)]\npub enum TableIndexCacheError {\n    #[error(\"Object store operation failed\")]\n    ObjectStore(#[source] object_store::Error),\n\n    #[error(\"JSON serialization/deserialization failed\")]\n    Json(#[source] serde_json::Error),\n\n    #[error(\"TableIndex operation failed\")]\n    TableIndex(#[source] crate::table_index::TableIndexError),\n\n    #[error(\"Object meta is missing filename\")]\n    MissingFilename,\n\n    #[error(\"Failed to parse snapshot sequence number from filename\")]\n    InvalidSnapshotSequenceNumber,\n\n    #[error(\"Unexpected error\")]\n    Unexpected(#[source] anyhow::Error),\n\n    #[error(\"Table snapshot persistence task failed\")]\n    TableSnapshotPersistenceTaskFailed(#[source] tokio::task::JoinError),\n\n    #[error(\"Failed to list table indices from object store\")]\n    ListIndices(#[source] object_store::Error),\n\n    #[error(\"Failed to parse table index path from object store path\")]\n    TableIndexPath(#[source] crate::paths::PathError),\n\n    #[error(\"Failed to list table index snapshots from object store\")]\n    ListSnapshots(#[source] object_store::Error),\n\n    #[error(\"Failed to parse table index snapshot path from object store path\")]\n    TableIndexSnapshotPath(#[source] crate::paths::PathError),\n\n    #[error(\"Failed to update table index: join task failed\")]","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_write/src/table_index_cache.rs#L39-L75","documentation":"TableIndexCacheError::Unexpected wraps an anyhow::Error for failures that do not fit the enumerated variants, e.g. persisting an updated index during purge_expired reports \"Failed to persist updated table index\" through this variant. It is a catch-all indicating an unclassified internal failure while maintaining table indexes.","triggerScenarios":"purge_expired's call to CoreTableIndex::persist fails and is converted via anyhow::anyhow! into TableIndexCacheError::Unexpected (table_index_cache.rs:937-942); other ad-hoc internal error paths also use this variant.","commonSituations":"Any underlying TableIndexError (object store I/O, JSON) surfacing from an index persist during retention/hard-delete operations, or genuinely unforeseen internal states — the wrapped message and source chain name the real cause.","solutions":["Read the anyhow message plus the #[source] chain to identify the real underlying failure and address that root cause.","If it is an object store I/O problem, verify store health, credentials, and network as for the ObjectStore variant.","If it occurs during retention/purge, retry the purge operation once the store is healthy; the index persist is idempotent per cutoff.","Consider improving the code to map the inner error to a typed variant instead of anyhow for better diagnostics."],"exampleFix":"// before\n.map_err(|e| TableIndexCacheError::Unexpected(anyhow::anyhow!(\"Failed to persist updated table index: {:?}\", e)))?\n// after\n.map_err(TableIndexCacheError::SplitPersistedSnapshotError)?","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_unexpected(e: &TableIndexCacheError) -> Option<&anyhow::Error> {\n    match e { TableIndexCacheError::Unexpected(a) => Some(a), _ => None }\n}","tryCatchPattern":"match cache.purge_expired(node, db, table, cutoff).await {\n    Err(e) if is_unexpected(&e).is_some() => {\n        error!(\"unclassified table index failure: {:?}\", e);\n        alert_and_retry().await\n    }\n    r => r?,\n}","preventionTips":["Always log the full anyhow source chain for Unexpected errors","Retry retention/purge operations once; they are idempotent per cutoff","File issues to convert anyhow catch-alls into typed variants for diagnosability","Check object store health first — most Unexpected errors wrap store I/O"],"tags":["rust","anyhow","catch-all","table-index"],"backgroundTag":"internal-invariant-violation","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}