{"record":{"id":"58f020a88a5ae556","repo":"clockworklabs/SpacetimeDB","slug":"insert-matches-accepted-row-diverged-from-model","errorCode":null,"errorMessage":"insert_matches: accepted row diverged from model","messagePattern":"insert_matches: accepted row diverged from model","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/dst/src/engine/properties.rs","lineNumber":107,"sourceCode":"        matches!(interaction, Interaction::Insert { .. })\n    }\n\n    fn check(\n        &self,\n        _interaction: &Interaction,\n        observation: &Observation,\n        expected: &Observation,\n    ) -> anyhow::Result<()> {\n        let Observation::Inserted { outcome } = observation else {\n            anyhow::bail!(\"insert_matches: insert produced unexpected observation\");\n        };\n        let Observation::Inserted { outcome: expected } = expected else {\n            unreachable!(\"InsertMatches only subscribes to insert interactions\");\n        };\n\n        match (outcome, expected) {\n            (InsertOutcome::Accepted(row), InsertOutcome::Accepted(expected)) => {\n                anyhow::ensure!(row == expected, \"insert_matches: accepted row diverged from model\");\n            }\n            (InsertOutcome::UniqueConstraintViolation, InsertOutcome::UniqueConstraintViolation) => {}\n            (InsertOutcome::Accepted(_), InsertOutcome::UniqueConstraintViolation) => {\n                anyhow::bail!(\"insert_matches: target accepted row rejected by model\");\n            }\n            (InsertOutcome::UniqueConstraintViolation, InsertOutcome::Accepted(_)) => {\n                anyhow::bail!(\"insert_matches: target rejected row accepted by model\");\n            }\n        }\n\n        Ok(())\n    }\n}\n\nstruct CommitMatches;\n\nimpl EngineProperty for CommitMatches {\n    fn observes(&self, interaction: &Interaction) -> bool {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/dst/src/engine/properties.rs#L89-L125","documentation":"Property InsertMatches failed: the engine accepted an insert, but the row it reports storing differs from the row predicted by the reference model oracle. Accepted rows carry engine-computed generated columns, so divergence means engine and model disagree on row content (generated-column values, normalization, or row encoding) — this is the harness detecting a suspected engine bug or a stale model, not a caller mistake.","triggerScenarios":"Running the dst property suite; inserting into a table whose generated columns are computed differently by the engine and by Model::apply; a change in row normalization or row_to_bytes encoding that was mirrored in only one of engine/model.","commonSituations":"Engine changes to generated columns or insert normalization without updating the model oracle; new table shapes in SchemaPlan exercising untested value types; encoding round-trip changes in the table layer.","solutions":["Log both rows (observation vs expected) and diff them field-by-field to find the diverging column","If a generated column diverges, compare the engine's computation with Model::apply for that column and fix the wrong side","If bytes diverge, check row_to_bytes round-trip for the failing value and the normalize_rows logic","Re-run with the failing seed after the fix to confirm the property holds"],"exampleFix":"// before: property failure gives only the message\nanyhow::ensure!(row == expected, \"insert_matches: accepted row diverged from model\");\n\n// after (debugging aid): report the differing columns\nfor (i, (a, b)) in row.iter().zip(expected.iter()).enumerate() {\n    if a != b { log::error!(\"col {i}: target={a:?} model={b:?}\"); }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match suite.observe(&interaction, &observation) {\n    Ok(()) => {}\n    Err(e) if e.to_string().contains(\"insert_matches: accepted row diverged from model\") => {\n        // persist the failing (interaction, observation) pair for shrinking;\n        // this is an engine/model disagreement, never auto-retry\n        shrinker.save_minimal_case(&interaction, &observation, &e);\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep the model oracle in the same PR as engine semantic changes (generated columns, normalization)","Run the dst property suite on every engine change with fixed seeds in CI","Log both target and model rows on divergence to speed up diagnosis"],"tags":["rust","spacetimedb","property-testing","oracle","invariant"],"backgroundTag":"property-test-oracle-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"}