{"record":{"id":"105d901d539dbb60","repo":"clockworklabs/SpacetimeDB","slug":"trapped-while-evaluating-views-during-database-upd","errorCode":null,"errorMessage":"Trapped while evaluating views during database update","messagePattern":"Trapped while evaluating views during database update","errorType":"exception","errorClass":"UpdateDatabaseResult::ErrorExecutingMigration","httpStatus":null,"severity":"error","filePath":"crates/core/src/host/wasm_common/module_host_actor.rs","lineNumber":732,"sourceCode":"\n                    tx_offset\n                };\n                let durable_offset = stdb.durable_tx_offset();\n\n                let res: UpdateDatabaseResult = match res {\n                    crate::db::update::UpdateResult::Success => {\n                        let tx_offset = succeed(self.info.clone(), FunctionBudget::ZERO, Duration::ZERO, tx);\n                        UpdateDatabaseResult::UpdatePerformed {\n                            tx_offset,\n                            durable_offset,\n                        }\n                    }\n                    crate::db::update::UpdateResult::EvaluateSubscribedViews => {\n                        let (out, _, trapped) = self.evaluate_subscribed_views(tx, inst)?;\n                        tx = out.tx;\n                        if trapped || out.outcome != ViewOutcome::Success {\n                            let msg = match trapped {\n                                true => \"Trapped while evaluating views during database update\".to_string(),\n                                false => format!(\n                                    \"Views evaluation did not complete successfully during database update: {:?}\",\n                                    out.outcome\n                                ),\n                            };\n\n                            let (_, tx_metrics, reducer) = stdb.rollback_mut_tx(tx);\n                            stdb.report_mut_tx_metrics(reducer, tx_metrics, None);\n                            UpdateDatabaseResult::ErrorExecutingMigration(anyhow::anyhow!(msg))\n                        } else {\n                            let tx_offset =\n                                succeed(self.info.clone(), out.execution_budget_used, out.total_duration, tx);\n                            UpdateDatabaseResult::UpdatePerformed {\n                                tx_offset,\n                                durable_offset,\n                            }\n                        }\n                    }","sourceCodeStart":714,"sourceCodeEnd":750,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/core/src/host/wasm_common/module_host_actor.rs#L714-L750","documentation":"During a database update (publish/migration), when the update engine requests subscribed-view evaluation, the host runs the views inside the update transaction. If any view traps — a wasm trap or panic while executing view code — this message is produced, the transaction is rolled back (with metrics reported), and the update fails as ErrorExecutingMigration. The database keeps its pre-update state; no partial migration is committed.","triggerScenarios":"Publishing an update where materialized/subscribed view code traps during the post-migration evaluation pass: view code that unwraps None, indexes out of bounds, or otherwise aborts when run against the migrated data.","commonSituations":"Views written against the old schema shape running once against new data during migration; views assuming non-empty tables or particular column values; migrations leaving data in a state the view code does not handle.","solutions":["Identify the trapping view from the update error context and host logs, then reproduce it against a copy of the production data.","Make view code total: replace unwrap/expect and unchecked indexing with handled cases.","Fix the migration so the data view code sees matches its expectations, or stage the view change in a later publish.","Retry the publish after the fix — the rollback guarantees no partial state from the failed attempt."],"exampleFix":"// before: view traps on empty state\nfn view(ctx: &ViewContext) -> Vec<JobRow> {\n    let first = ctx.table::<Job>().iter().next().unwrap();\n    vec![first.into()]\n}\n\n// after: tolerate the empty case instead of trapping\nfn view(ctx: &ViewContext) -> Vec<JobRow> {\n    ctx.table::<Job>().iter().take(1).map(Into::into).collect()\n}","handlingStrategy":"try-catch","validationCode":"// Before publishing an update, run all views against a restored snapshot\nfor view in module.views() {\n    evaluate_view(view, snapshot_db.clone())?; // must not trap on migrated data\n}","typeGuard":null,"tryCatchPattern":"match update_result {\n    UpdateDatabaseResult::ErrorExecutingMigration(e) => {\n        // transaction was rolled back automatically — fix the trapping view, then republish\n        log::warn!(\"update rejected: {e:#}\");\n    }\n    other => { /* ... */ }\n}","preventionTips":["Never unwrap/expect or index unchecked inside view code.","Test the full publish against a database snapshot before production.","Keep views tolerant of empty and edge-case data."],"tags":["views","migration","trap","database-update"],"backgroundTag":"wasm-trap","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}