{"record":{"id":"30956b8da61a09b9","repo":"clockworklabs/SpacetimeDB","slug":"insert-without-active-mutable-transaction","errorCode":null,"errorMessage":"insert without active mutable transaction","messagePattern":"insert without active mutable transaction","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/dst/src/engine.rs","lineNumber":216,"sourceCode":"                );\n                let db = self\n                    .db\n                    .as_ref()\n                    .ok_or_else(|| anyhow::anyhow!(\"database is not open\"))?;\n                self.active_mut_tx = Some(db.begin_mut_tx(IsolationLevel::Serializable, Workload::Internal));\n                Ok(Observation::BeganMutTx)\n            }\n            Interaction::Insert { table, row } => {\n                let table_id = self.table_ids[*table];\n                let bytes = row_to_bytes(row);\n                let db = self\n                    .db\n                    .as_ref()\n                    .ok_or_else(|| anyhow::anyhow!(\"database is not open\"))?;\n                let tx = self\n                    .active_mut_tx\n                    .as_mut()\n                    .ok_or_else(|| anyhow::anyhow!(\"insert without active mutable transaction\"))?;\n                let outcome = match db.insert(tx, table_id, &bytes) {\n                    Ok((_generated_columns, row, _flags)) => InsertOutcome::Accepted(row.to_product_value()),\n                    // Generated rows can intentionally hit unique constraints; the oracle validates that rejection.\n                    Err(error) if Self::is_unique_constraint_violation(&error) => {\n                        InsertOutcome::UniqueConstraintViolation\n                    }\n                    Err(error) => return Err(error.into()),\n                };\n                Ok(Observation::Inserted { outcome })\n            }\n            Interaction::Delete { table, row } => {\n                let table_id = self.table_ids[*table];\n                let db = self\n                    .db\n                    .as_ref()\n                    .ok_or_else(|| anyhow::anyhow!(\"database is not open\"))?;\n                let tx = self\n                    .active_mut_tx","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/dst/src/engine.rs#L198-L234","documentation":"Insert interactions in the dst engine require an open mutable transaction: self.active_mut_tx was None because no BeginMutTx was issued, or the previous transaction already ended via CommitTx (or was discarded by Replay).","triggerScenarios":"An interaction sequence starting with Insert instead of BeginMutTx; Insert after CommitTx without beginning a new transaction; Insert after a Replay interaction (which drops the active tx) without re-beginning.","commonSituations":"Workload-generator state machine bugs that skip the begin edge; hand-written interaction scripts in DST tests; refactors of the sequence builder.","solutions":["Wrap every Insert/Delete block in BeginMutTx ... CommitTx","Model tx-open/tx-closed as states in the generator and only emit data ops in the open state","Remember Replay discards the active transaction — emit BeginMutTx again after it","Add an assertion in the driver that data ops only follow a successful BeganMutTx observation"],"exampleFix":"// before: insert with no transaction open\nvec![Insert { .. }, Delete { .. }, CommitTx]\n\n// after: open a transaction first, then operate, then commit\nvec![BeginMutTx, Insert { .. }, Delete { .. }, CommitTx]","handlingStrategy":"validation","validationCode":"// Sequence-level guard before emitting an Insert\nfn sequence_allows_insert(tx_active: bool) -> bool {\n    tx_active\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate interactions from a tx state machine so data ops only appear inside an open transaction","Begin a fresh transaction after every CommitTx or Replay before any data op","Assert that Insert/Delete always follows a BeganMutTx observation in test properties"],"tags":["rust","spacetimedb","dst","testing","transaction","state-machine"],"backgroundTag":"no-active-transaction","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"}