{"record":{"id":"7e409261539b11cf","repo":"clockworklabs/SpacetimeDB","slug":"when-replaying-st-column-update-table-type-sh","errorCode":null,"errorMessage":"When replaying `st_column` update: `table_type` should not have changed, but previous schema has {:?} and new schema has {:?}","messagePattern":"When replaying `st_column` update: `table_type` should not have changed, but previous schema has (.+?) and new schema has (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/datastore/src/locking_tx_datastore/replay.rs","lineNumber":857,"sourceCode":"            .expect(\"`st_table` should exist\")\n            .any(|row_ref| row_ref.pointer() != new_st_table_entry.pointer())\n    }\n\n    /// Update the in-memory table structure for the table described by `row`,\n    /// in response to replay of a schema-altering migration.\n    fn reschema_table_for_st_table_update(&mut self, row: StTableRow) -> Result<()> {\n        // We only need to update if we've already constructed the in-memory table structure.\n        // If we haven't yet, then `self.get_table_and_blob_store_or_create` will see the correct schema\n        // when it eventually runs.\n        if let Ok((table, ..)) = self.get_table_and_blob_store_mut(row.table_id) {\n            table.with_mut_schema(|schema| -> Result<()> {\n                schema.table_access = row.table_access;\n                schema.primary_key = row.table_primary_key.map(|col_list| col_list.as_singleton().ok_or_else(|| anyhow::anyhow!(\"When replaying `st_column` update: `table_primary_key` should be a single column, but found {col_list:?}\"))).transpose()?;\n                schema.table_name = row.table_name;\n                if row.table_type == schema.table_type {\n                    Ok(())\n                } else {\n                    Err(anyhow::anyhow!(\n                    \"When replaying `st_column` update: `table_type` should not have changed, but previous schema has {:?} and new schema has {:?}\",\n                    schema.table_type,\n                    row.table_type,\n                ).into())\n}\n            })?;\n        }\n        Ok(())\n    }\n\n    /// Mark all `st_column` rows which refer to the same column as `st_column_row`\n    /// other than the one at `row_pointer` as outdated\n    /// by storing them in [`Self::replay_columns_to_ignore`].\n    ///\n    /// Returns the ID of the table to which `st_column_row` belongs.\n    fn ignore_previous_versions_of_column(\n        &mut self,\n        st_column_row: &ProductValue,","sourceCodeStart":839,"sourceCodeEnd":875,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/datastore/src/locking_tx_datastore/replay.rs#L839-L875","documentation":"While replaying an st_table update, the in-memory schema for that table already exists and its table_type (user vs system) differs from the value in the replayed st_table row. table_type is immutable for the lifetime of a table, so the commitlog disagrees with the state derived earlier in replay — corruption, version divergence, or a bug rewriting st_table rows.","triggerScenarios":"Replaying a commitlog whose st_table row for an existing table carries a different table_type than the schema built earlier in the same replay; produced by log corruption, version skew, or faulty system-table rewrites.","commonSituations":"Opening a data directory with a mismatched spacetimedb build; crash during a system-table rewrite; databases migrated between versions that changed system-table semantics.","solutions":["Open the database with the spacetimedb version that produced it","Restore from a known-good snapshot","Recreate the database if the data is disposable","File a bug with the commitlog — table_type must never change for a given TableId"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"Catch at open time, log the previous and replayed table_type from the message, and restore from a known-good snapshot; a table_type change is never legitimate, so treat the data dir as tainted.","preventionTips":["Keep binaries version-locked to the data they open","Validate backups by opening them after every upgrade","Monitor for crashes during system-table rewrites and re-snapshot afterwards"],"tags":["rust","spacetimedb","replay","schema","corruption","version-skew"],"backgroundTag":"schema-mismatch","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}