{"record":{"id":"9ff28049d41ce856","repo":"tursodatabase/turso","slug":"page-should-be-present","errorCode":null,"errorMessage":"page should be present","messagePattern":"page should be present","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/storage/btree.rs","lineNumber":8088,"sourceCode":"        else {\n            return Ok(IOResult::Done(()));\n        };\n        turso_assert!(\n            page_idx >= 0,\n            \"pages should be positive during integrity check\"\n        );\n        let page = match state.page.take() {\n            Some(page) => page,\n            None => {\n                // On `IO(spill_c)` we leave `state.page = None` so re-entry\n                // re-takes this None branch and resumes via the pager's\n                // `pending_reads` memoization.\n                let (page, c) = return_if_io!(pager.read_page(page_idx));\n                state.page = Some(page);\n                if let Some(c) = c {\n                    io_yield_one!(c);\n                }\n                state.page.take().expect(\"page should be present\")\n            }\n        };\n        turso_assert!(page.is_loaded(), \"page should be loaded\");\n        state.page_stack.pop();\n\n        let contents = page.get_contents();\n        if page_category == PageCategory::FreeListTrunk {\n            state.freelist_count.actual_count += 1;\n            let next_freelist_trunk_page =\n                contents.read_u32_no_offset(FREELIST_TRUNK_OFFSET_NEXT_TRUNK_PTR);\n            if next_freelist_trunk_page != 0 {\n                if next_freelist_trunk_page as usize > state.db_size {\n                    tracing::error!(\n                        \"integrity_check: freelist trunk page {} has invalid next pointer {}. header_bytes={:02x?}\",\n                        page.get().id(),\n                        next_freelist_trunk_page,\n                        &contents.as_ptr()[0..16]\n                    );","sourceCodeStart":8070,"sourceCodeEnd":8106,"githubUrl":"https://github.com/tursodatabase/turso/blob/492c4a71cd7c2649e7df83da1471b74f4b1c7aa9/core/storage/btree.rs#L8070-L8106","documentation":"Inside integrity_check()'s page-walk loop (core/storage/btree.rs): when state.page is None on re-entry, the loop reads the page, stores it in state.page, yields any read completion, then immediately takes it back with expect(\"page should be present\"). Because the take happens right after the store in the same basic block, this assert is effectively a defensive self-check for state-machine re-entry bugs.","triggerScenarios":"Running PRAGMA integrity_check (which also validates the freelist) on a database with freelist trunk/leaf pages. The expect could only fire if state.page were cleared between the store and the take - i.e. concurrent re-entry of the integrity-check state machine.","commonSituations":"Integrity checks on large or spilled databases where reads yield IO; engine regressions in integrity-check re-entrancy.","solutions":["Rerun the integrity check on a copy of the database with a single connection to rule out re-entrancy","Report to Turso if it reproduces - it marks a state-machine re-entry bug, not data corruption per se","Run the check on an older/newer engine build to bisect a regression","Verify the database afterwards with sqlite3's PRAGMA integrity_check as a cross-check"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Run the integrity check single-threaded on a copy first - the assert guards\n// against re-entrant state-machine use, so eliminate concurrency:\nlet copy = std::path::Path::new(\"/tmp/check-copy.db\");\nstd::fs::copy(&db_path, copy)?;\nlet conn = Connection::open(copy)?;\nlet report = conn.query_row(\"PRAGMA integrity_check\", [], |r| r.get::<_, String>(0))?;","typeGuard":null,"tryCatchPattern":"let result = std::panic::catch_unwind(AssertUnwindSafe(|| run_integrity_check(&conn)));\nmatch result {\n    Ok(Ok(report)) => /* inspect report */,\n    Ok(Err(e)) => /* surfaced DB error */,\n    Err(_) => /* engine state bug: report upstream, cross-check with sqlite3 CLI */,\n}","preventionTips":["Run integrity checks on a connection with no concurrent statements","Cross-validate suspicious databases with the sqlite3 CLI's integrity_check","Treat a panic here as an engine bug signal, not evidence of corruption by itself"],"tags":["integrity-check","freelist","defensive-assert","panic"],"backgroundTag":"database-integrity-check-failed","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"}