{"record":{"id":"ed187519c99937b9","repo":"clockworklabs/SpacetimeDB","slug":"when-replaying-st-column-update-table-primary","errorCode":null,"errorMessage":"When replaying `st_column` update: `table_primary_key` should be a single column, but found {col_list:?}","messagePattern":"When replaying `st_column` update: `table_primary_key` should be a single column, but found (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/datastore/src/locking_tx_datastore/replay.rs","lineNumber":852,"sourceCode":"                .expect(\"`st_table` row should conform to `st_table` schema\")\n        }\n\n        let referenced_table_id = get_table_id(new_st_table_entry);\n        self.iter_by_col_eq(ST_TABLE_ID, StTableFields::TableId, &referenced_table_id.into())\n            .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`].","sourceCodeStart":834,"sourceCodeEnd":870,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/datastore/src/locking_tx_datastore/replay.rs#L834-L870","documentation":"During replay of a schema-altering st_table update, reschema_table_for_st_table_update maps the stored table_primary_key list into the in-memory schema via ColList::as_singleton, which requires exactly one column. The replayed row carries a multi-column list, so the update cannot be applied and replay fails. The locking datastore models primary keys as a single column (identity/sequence), so a composite PK in st_table is un-replayable.","triggerScenarios":"A commitlog containing an st_table row whose table_primary_key list has more than one element — written by a different or experimental spacetimedb build, hand-crafted, or by a newer version introducing composite PKs that an older binary then tries to replay.","commonSituations":"Version skew between the binary that wrote the log and the one replaying it; replaying logs from experimental feature branches; downgrade compatibility testing.","solutions":["Replay with the same spacetimedb version that wrote the commitlog","If composite primary keys are required, upgrade every node that will open the database","Restore from a snapshot taken with a compatible version","Report the incompatibility — the message includes the offending col list"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"Wrap database open; on this schema-mismatch error abort the open, report the version pair in the message to operators, and fall back to a snapshot from a compatible version.","preventionTips":["Pin the spacetimedb version across all nodes that share commitlogs","Never replay logs written by experimental builds with a stable build","Verify composite-PK support in both writer and reader versions before deploying schema changes"],"tags":["rust","spacetimedb","replay","primary-key","schema","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-14T00:17:10.932Z"}