{"record":{"id":"333099a97d2014f8","repo":"tursodatabase/turso","slug":"result-should-be-set","errorCode":null,"errorMessage":"result should be set","messagePattern":"result should be set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/storage/pager.rs","lineNumber":4858,"sourceCode":"        state.lock_source = CheckpointLockSource::Acquire;\n    }\n\n    /// Clean up after a auto-checkpoint failure.\n    /// Auto-checkpoint executed outside of the main transaction - so WAL transaction was already finalized\n    pub fn cleanup_after_auto_checkpoint_failure(&self) {\n        self.cleanup_after_checkpoint_failure();\n    }\n\n    pub fn cleanup_after_checkpoint_failure(&self) {\n        self.reset_checkpoint_state();\n        if let Some(wal) = self.wal.as_ref() {\n            wal.abort_checkpoint();\n        }\n    }\n\n    fn next_post_sync_checkpoint_phase(&self, clear_page_cache: bool) -> CheckpointPhase {\n        let state = self.checkpoint_state.read();\n        let result = state.result.as_ref().expect(\"result should be set\");\n        let mode = state.mode.expect(\"mode should be set\");\n        if result.wal_checkpoint_backfilled > 0\n            && !matches!(\n                mode,\n                CheckpointMode::Restart | CheckpointMode::Truncate { .. }\n            )\n        {\n            // if we are using a custom codec, then we might have to read the whole page 1 so that\n            // it can be decoded. Otherwise reading the header is enough.\n            let read_page = self.io_ctx.read().has_codec_transform();\n            let read_size = if read_page {\n                self.get_page_size_unchecked().get() as usize\n            } else {\n                PageSize::MIN as usize\n            };\n            return CheckpointPhase::ReadDbIdentity {\n                clear_page_cache,\n                read: PendingCheckpointDbIdentityRead {","sourceCodeStart":4840,"sourceCodeEnd":4876,"githubUrl":"https://github.com/tursodatabase/turso/blob/492c4a71cd7c2649e7df83da1471b74f4b1c7aa9/core/storage/pager.rs#L4840-L4876","documentation":"Turso's pager runs WAL checkpoints as an async state machine. After a checkpoint's sync phase completes, next_post_sync_checkpoint_phase (core/storage/pager.rs:4583) locks the shared checkpoint state and unwraps state.result (a CheckpointResult stored in the state struct, pager.rs:1035) with expect(\"result should be set\"). The panic means the pager tried to compute the next checkpoint phase while checkpoint_state.result was None - an internal invariant violation, typically a race where the checkpoint state was reset (e.g. by cleanup_after_checkpoint_failure -> reset_checkpoint_state after an I/O error) while a post-sync phase transition at pager.rs:4813 was still in flight.","triggerScenarios":"Issuing PRAGMA wal_checkpoint (especially RESTART/TRUNCATE/FULL) that reaches the post-sync phase transition at pager.rs:4813 after checkpoint state was reset by cleanup_after_checkpoint_failure(); concurrent wal_checkpoint calls from multiple connections racing an abort; checkpoints on databases where wal_checkpoint_backfilled > 0, which takes the page-1 re-read branch when the DB has a codec transform (has_codec_transform).","commonSituations":"Concurrent checkpointing under load, checkpoint retry after a transient I/O error, encrypted/codec-wrapped databases, custom VFS with fault injection, WAL stress or MVCC test workloads, engine version skew after a checkpoint-state-machine refactor.","solutions":["Re-run with RUST_BACKTRACE=1 to capture the full panic trace and note the exact sequence of checkpoint calls, then report it as a Turso engine bug with a minimal reproduction - this is an internal state-machine bug, not caller error.","Upgrade to the latest tursodb release; the checkpoint state machine is actively developed and the race may already be fixed.","Serialize checkpoints: let a single connection run PRAGMA wal_checkpoint instead of several connections checkpointing concurrently.","If it reproduces on an encrypted/codec database or after an injected I/O failure, include that detail in the bug report (both branches are visible in the code path)."],"exampleFix":"-- before: multiple connections checkpointing concurrently\n-- conn A: PRAGMA wal_checkpoint(TRUNCATE);\n-- conn B: PRAGMA wal_checkpoint(TRUNCATE);\n\n-- after: single dedicated connection, others just write\n-- checkpoint conn: PRAGMA wal_checkpoint(TRUNCATE);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"Rust host: wrap the checkpoint call in std::panic::catch_unwind (AssertUnwindSafe) to contain the engine panic, then treat the checkpoint as failed and retry later. Python/JS bindings: catch the RuntimeError the panic is surfaced as around `PRAGMA wal_checkpoint` execution.","preventionTips":["Run PRAGMA wal_checkpoint from a single dedicated connection instead of checkpointing concurrently from many connections.","Keep tursodb pinned to a version you have stress-tested; re-test checkpoints (RESTART/TRUNCATE) after every engine upgrade.","Run with RUST_BACKTRACE=1 in staging so any invariant panic carries a usable trace.","Avoid issuing checkpoints while injecting I/O failures or running codec/encrypted databases together with concurrent checkpoint load until the state machine is fixed."],"tags":["rust","panic","checkpoint","wal","pager","invariant","concurrency","turso"],"backgroundTag":"rust-invariant-panic","analyzedSha":"492c4a71cd7c2649e7df83da1471b74f4b1c7aa9","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}