{"record":{"id":"fbebe1bfd9e304ff","repo":"clockworklabs/SpacetimeDB","slug":"deletion-for-non-existent-table-table-id-hu","errorCode":null,"errorMessage":"Deletion for non-existent table {table_id:?}... huh?","messagePattern":"Deletion for non-existent table (.+?)\\.\\.\\. huh\\?","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/datastore/src/locking_tx_datastore/committed_state.rs","lineNumber":662,"sourceCode":"                let truncated = table.row_count == 0;\n                if truncated {\n                    truncates.insert(table_id);\n                }\n            }\n        }\n\n        for (table_id, row_ptrs) in delete_tables {\n            match self.get_table_and_blob_store_mut(table_id) {\n                Ok((table, blob_store, ..)) => delete_rows(\n                    tx_data,\n                    table_id,\n                    table,\n                    blob_store,\n                    row_ptrs.len(),\n                    row_ptrs.iter(),\n                    truncates,\n                ),\n                Err(_) if !row_ptrs.is_empty() => panic!(\"Deletion for non-existent table {table_id:?}... huh?\"),\n                Err(_) => {}\n            }\n        }\n\n        // Delete all tables marked for deletion.\n        // The order here does not matter as once a `table_id` has been dropped\n        // it will never be re-created.\n        for change in pending_schema_changes {\n            if let PendingSchemaChange::TableRemoved(table_id, mut table) = change {\n                let row_ptrs = table.scan_all_row_ptrs();\n                truncates.insert(table_id);\n                delete_rows(\n                    tx_data,\n                    table_id,\n                    &mut table,\n                    &mut self.blob_store,\n                    row_ptrs.len(),\n                    row_ptrs.into_iter(),","sourceCodeStart":644,"sourceCodeEnd":680,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/datastore/src/locking_tx_datastore/committed_state.rs#L644-L680","documentation":"While applying a committed transaction's deletions, the datastore looks up each table targeted by delete operations (get_table_and_blob_store_mut). The Err arm with an empty row_ptrs set is tolerated as a no-op (deleting zero rows from a missing table), but finding actual row pointers to delete in a table absent from the committed state means transaction state is inconsistent, so the code panics ('... huh?'). This is an internal locking-datastore invariant violation, not an API misuse by callers.","triggerScenarios":"Committing a MutTx whose delete set references rows in a table that no longer exists in committed state, e.g. interleaved table-drop schema changes with pending row deletions in the same epoch (the code right below also processes pending_schema_changes TableRemoved).","commonSituations":"Almost always a spacetimedb engine bug; can surface under concurrent reducers mixing DDL (drop/truncate) with row deletion on the same table, or after an upgrade changed schema-change bookkeeping.","solutions":["Reproduce with a minimal reducer sequence (create/insert/delete/drop on one table) and report upstream with the panic backtrace.","Upgrade to the latest spacetimedb patch release, where invariant fixes land.","Work around by separating schema changes from data mutations: stop writers, apply the drop, then resume."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// isolate engine panics at the task boundary so one bad commit does not kill the worker\nlet outcome = tokio::task::spawn_blocking(move || run_reducers(db, tx)).await;\nmatch outcome {\n    Ok(r) => r,\n    Err(join_err) if join_err.is_panic() => {\n        // datastore invariant violation: snapshot workload, report upstream, restart worker\n        report_invariant(join_err.into_panic());\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Keep spacetimedb updated; this panic is an engine bug, not user error.","Avoid mixing table-drop DDL with concurrent row deletions on the same table.","Keep a minimal reproducer harness ready to attach to upstream reports.","Back up commitlogs so any reproduction can be shared safely."],"tags":["spacetimedb","datastore","invariant","panic","internal-bug"],"backgroundTag":"datastore-invariant-violation","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}