{"record":{"id":"b990bff4bfff28e4","repo":"influxdata/influxdb","slug":"failed-to-delete-table-index-snapshot-from-object-store","errorCode":null,"errorMessage":"Failed to delete table index snapshot from object store","messagePattern":"Failed to delete table index snapshot from object store","errorType":"error_code","errorClass":"TableIndexError","httpStatus":null,"severity":"warning","filePath":"influxdb3_write/src/table_index.rs","lineNumber":46,"sourceCode":"    #[error(\"Failed to deserialize table index\")]\n    DeserializeIndex(#[source] serde_json::Error),\n\n    #[error(\"Failed to list table index snapshots from object store\")]\n    ListSnapshots(#[source] object_store::Error),\n\n    #[error(\"Failed to list table indices from object store\")]\n    ListIndices(#[source] object_store::Error),\n\n    #[error(\"Failed to load table index snapshot from object store\")]\n    LoadSnapshot(#[source] object_store::Error),\n\n    #[error(\"Failed to deserialize table index snapshot\")]\n    DeserializeSnapshot(#[source] serde_json::Error),\n\n    #[error(\"Failed to persist table index to object store\")]\n    PersistIndex(#[source] object_store::Error),\n\n    #[error(\"Failed to delete table index snapshot from object store\")]\n    DeleteSnapshot(#[source] object_store::Error),\n\n    #[error(\"Cannot merge table indices with mismatched identifiers: {expected} != {actual}\")]\n    MergeMismatch {\n        expected: TableIndexId,\n        actual: TableIndexId,\n    },\n\n    #[error(\"Failed to parse table index path from object store path\")]\n    TableIndexPath(#[source] crate::paths::PathError),\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\")]\n    UpdateTaskFailed(#[source] tokio::task::JoinError),\n\n    #[error(\"Object meta is missing filename\")]","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_write/src/table_index.rs#L28-L64","documentation":"TableIndexError::DeleteSnapshot is raised when deleting a persisted table index snapshot object from the object store fails. Snapshot cleanup (removal of superseded snapshot files) is part of the index maintenance flow; if the object_store delete call returns an error, it is wrapped here. A failure here usually means stale snapshots accumulate rather than data loss.","triggerScenarios":"Calling the cleanup path that invokes ObjectStore::delete (or delete_prefix) on a TableIndexSnapshotPath object and the store returns a permission, network, throttling, or not-found-handled-as-error condition.","commonSituations":"IAM policy allows writes but not DeleteObject; transient S3/GCS unavailability during garbage collection; another process/node already deleted the snapshot concurrently; bucket versioning/retention policies blocking deletes.","solutions":["Inspect the wrapped object_store::Error; treat NotFound as benign and continue.","Grant the service account/role DeleteObject (or s3:DeleteObject) permission.","Retry the cleanup with backoff — deletes are idempotent, so retrying is safe.","Check bucket retention/versioning/lifecycle policies that may block object deletion."],"exampleFix":"// before\nstore.delete(&snapshot_path).await.map_err(TableIndexError::DeleteSnapshot)?;\n// after\nmatch store.delete(&snapshot_path).await {\n    Err(e) if e.to_string().contains(\"NotFound\") => {} // already deleted, ok\n    Err(e) => return Err(TableIndexError::DeleteSnapshot(e)),\n    Ok(_) => {}\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"fn is_benign_delete_failure(e: &object_store::Error) -> bool {\n    matches!(e, object_store::Error::NotFound{..}) || e.to_string().contains(\"404\")\n}","tryCatchPattern":"match store.delete(&path).await {\n    Ok(_) => {},\n    Err(e) if is_benign_delete_failure(&e) => {}, // already gone\n    Err(e) => return Err(TableIndexError::DeleteSnapshot(e)),\n}","preventionTips":["Grant DeleteObject alongside write permissions.","Treat not-found on delete as success — deletes are idempotent.","Retry cleanup loops with backoff; never crash GC on a single delete failure.","Review bucket retention/lifecycle policies before enabling snapshot cleanup."],"tags":["object-store","delete","cleanup","io"],"backgroundTag":"database-write-failed","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"}