{"record":{"id":"f9670f54265fabe0","repo":"tursodatabase/turso","slug":"subjournal-must-be-opened","errorCode":null,"errorMessage":"subjournal must be opened","messagePattern":"subjournal must be opened","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/storage/pager.rs","lineNumber":2198,"sourceCode":"                    .write_offset\n                    .fetch_add(page_size as u64 + 4, Ordering::SeqCst);\n            })\n        };\n        let c = Completion::new_write(write_complete);\n\n        let subjournal = self.subjournal.read();\n        let subjournal = subjournal.as_ref().unwrap();\n\n        let c = subjournal.write_page(write_offset, page_size, buffer, c)?;\n        turso_assert!(c.succeeded(), \"memory IO should complete immediately\");\n        Ok(())\n    }\n\n    /// try to \"acquire\" ownership on the subjournal of the connection-scoped pager\n    /// if another statement owns the subjournal - return Busy error and let the caller retry attempt later\n    pub fn try_use_subjournal(&self) -> Result<()> {\n        let subjournal = self.subjournal.read();\n        let subjournal = subjournal.as_ref().expect(\"subjournal must be opened\");\n        subjournal.try_use()\n    }\n\n    /// release ownership of the subjournal\n    /// caller must guarantee that [Self::stop_use_subjournal] is called only after successful call to the [Self::try_use_subjournal]\n    pub fn stop_use_subjournal(&self) {\n        let subjournal = self.subjournal.read();\n        let subjournal = subjournal.as_ref().expect(\"subjournal must be opened\");\n        subjournal.stop_use()\n    }\n\n    /// check if subjournal is in use for some statement\n    pub fn subjournal_in_use(&self) -> bool {\n        let subjournal = self.subjournal.read();\n        let Some(subjournal) = subjournal.as_ref() else {\n            return false;\n        };\n        subjournal.in_use()","sourceCodeStart":2180,"sourceCodeEnd":2216,"githubUrl":"https://github.com/tursodatabase/turso/blob/492c4a71cd7c2649e7df83da1471b74f4b1c7aa9/core/storage/pager.rs#L2180-L2216","documentation":"Pager::try_use_subjournal() acquires statement-level ownership of the subjournal (the in-memory before-image store used for statement rollback). It expects the subjournal to have been created first via open_subjournal(); all in-engine call sites pair them as open_subjournal()? then try_use_subjournal()?. Calling try before a successful open panics with \"subjournal must be opened\".","triggerScenarios":"Code calling pager.try_use_subjournal() on a connection-scoped pager where open_subjournal() has not run, or where its Result was ignored and it failed before storing the Subjournal.","commonSituations":"Embedders driving the pager directly outside the VDBE flow, refactors that drop the open call on an error path, custom statement implementations.","solutions":["Call pager.open_subjournal()? immediately before pager.try_use_subjournal()?","Never ignore the Result of open_subjournal - propagate errors before acquiring ownership","In debug builds, assert the subjournal exists before acquiring"],"exampleFix":"// before\npager.try_use_subjournal()?; // panics: subjournal was never opened\n\n// after\npager.open_subjournal()?;\npager.try_use_subjournal()?;","handlingStrategy":"validation","validationCode":"// Acquire the subjournal in the documented order before use:\npager.open_subjournal()?;      // creates the in-memory subjournal\npager.try_use_subjournal()?;   // now safe: acquires statement ownership","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call open_subjournal()? immediately before try_use_subjournal()? - mirror the VDBE call sites","Propagate open_subjournal errors; never assume it succeeded implicitly","Keep custom pager-driving code in sync with engine call-site patterns (vdbe/mod.rs, vdbe/execute.rs)"],"tags":["pager","subjournal","savepoint","api-misuse","panic"],"backgroundTag":"resource-not-initialized","analyzedSha":"492c4a71cd7c2649e7df83da1471b74f4b1c7aa9","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}