{"record":{"id":"e0e8dbe84f50d74e","repo":"tursodatabase/turso","slug":"finished-unsuccessful-cacheflush-read-must-have-an","errorCode":null,"errorMessage":"finished unsuccessful cacheflush read must have an error","messagePattern":"finished unsuccessful cacheflush read must have an error","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/storage/pager.rs","lineNumber":4048,"sourceCode":"        // All pages collected and written\n        Ok(CacheFlushStep::Done(state.completions))\n    }\n\n    /// Handle completion of async page read for evicted page.\n    fn cacheflush_handle_read(\n        &self,\n        wal: &Arc<dyn Wal>,\n        page_sz: PageSize,\n        mut state: CollectingState,\n        page_id: usize,\n        page: PageRef,\n        completion: Completion,\n    ) -> Result<CacheFlushStep> {\n        if !completion.succeeded() {\n            if completion.finished() {\n                let err = completion\n                    .get_error()\n                    .expect(\"finished unsuccessful cacheflush read must have an error\");\n                return Err(err.into());\n            }\n            return Ok(CacheFlushStep::Yield(\n                CacheFlushState::WaitingForRead {\n                    state,\n                    page_id,\n                    page,\n                    completion: completion.clone(),\n                },\n                IOCompletions(completion),\n            ));\n        }\n        trace!(\n            \"cacheflush(page={}, page_type={:?}) [re-read complete]\",\n            page_id,\n            page.get_contents().page_type().ok()\n        );\n        state.collected_pages.push(page);","sourceCodeStart":4030,"sourceCodeEnd":4066,"githubUrl":"https://github.com/tursodatabase/turso/blob/492c4a71cd7c2649e7df83da1471b74f4b1c7aa9/core/storage/pager.rs#L4030-L4066","documentation":"Cache-flush state machine (core/storage/pager.rs): when a page-read Completion reports finished-but-unsuccessful, the code retrieves the error with completion.get_error().expect(\"finished unsuccessful cacheflush read must have an error\"). The completion contract is finished + !succeeded implies an error was recorded; a completion that finishes failed without an error payload violates it.","triggerScenarios":"A real IO error during a cache-flush page read (disk read failure, bad sector, IO driver fault) where the Completion object reached the finished state without storing its error.","commonSituations":"Custom IO implementations with buggy completion handling (finishing without set_error), OS-level read errors surfacing mid-flush, engine regressions in Completion plumbing.","solutions":["If you provide a custom IO implementation, always record the error on the Completion before completing it on failure","For built-in IO backends, treat occurrences as an engine bug: report the IO backend and system state","Fix the underlying storage issue (disk health, permissions) and retry","Run PRAGMA integrity_check afterwards to verify database pages"],"exampleFix":"// before (custom IO implementation)\nlet completion = Completion::new_read(|_| {});\ncomplete_failed_without_error(completion); // finishes, !succeeded, no error -> engine panics\n\n// after\nlet completion = Completion::new_read(|_| {});\ncompletion.set_error(CompletionError::IOError(errno));\ncomplete(completion);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let result = std::panic::catch_unwind(AssertUnwindSafe(|| do_heavy_read_workload(&conn)));\nif result.is_err() {\n    conn.close().ok();\n    // Check storage health, then reopen and verify:\n    //   PRAGMA integrity_check;\n}","preventionTips":["If you implement the IO trait, always record an error on the Completion before completing it in failure paths","Surface and log IO-level errors from your storage layer instead of swallowing them","Monitor disk health; real read failures underlie most completions finishing unsuccessfully","Run integrity checks after IO errors to detect damaged pages"],"tags":["pager","io-completion","cache-flush","panic"],"backgroundTag":"async-io-completion-error","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"}