{"record":{"id":"b3ad2d32269d14c7","repo":"t8y2/dbx","slug":"sqlite-worker-has-no-open-database","errorCode":null,"errorMessage":"SQLite worker has no open database","messagePattern":"SQLite worker has no open database","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbx-sqlite-worker/src/runtime.rs","lineNumber":48,"sourceCode":"        if matches!(response.body, WorkerBody::Ok { .. }) {\n            // keep serving\n        }\n    }\n    Ok(())\n}\n\nfn handle(connection: &mut Option<Connection>, request: WorkerRequest) -> WorkerResponse {\n    let body = match request.op {\n        WorkerOp::Open { path } => match open_database(&path) {\n            Ok(opened) => {\n                *connection = Some(opened);\n                WorkerBody::ok()\n            }\n            Err(error) => WorkerBody::err(error),\n        },\n        WorkerOp::Query { sql, max_rows } => match connection.as_mut() {\n            Some(conn) => query(conn, &sql, max_rows.unwrap_or(10_000)),\n            None => WorkerBody::err(\"SQLite worker has no open database\"),\n        },\n        WorkerOp::Backup { dest } => match connection.as_mut() {\n            Some(conn) => backup(conn, &dest),\n            None => WorkerBody::err(\"SQLite worker has no open database\"),\n        },\n        WorkerOp::Restore { src } => match connection.as_mut() {\n            Some(conn) => restore(conn, &src),\n            None => WorkerBody::err(\"SQLite worker has no open database\"),\n        },\n        WorkerOp::Ping => WorkerBody::pong(),\n        WorkerOp::Close => {\n            *connection = None;\n            WorkerBody::ok()\n        }\n    };\n    WorkerResponse { id: request.id, body }\n}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/crates/dbx-sqlite-worker/src/runtime.rs#L30-L66","documentation":"The SQLite worker's Query operation was received while no database connection is open. The worker protocol requires an Open (or successful open path) before Query; otherwise it replies with this error body instead of panicking on a null connection.","triggerScenarios":"Sending WorkerOp::Query before WorkerOp::Open; after a Close operation; after a failed/aborted open; reusing a worker whose connection was never established because an earlier open errored.","commonSituations":"Client code that skips the open step assuming auto-connect; connection lost/closed by an earlier failed operation; test harnesses exercising ops without setup.","solutions":["Send WorkerOp::Open with a valid database path before any Query","Check the result of the Open op and handle its error before proceeding","If a Close was issued, reopen before issuing further ops","Pool workers so each op sequence starts with a successful open"],"exampleFix":"// before\nsend(Query { sql }); // no prior open\n// after\nsend(Open { path: \"app.db\" });\nsend(Query { sql });","handlingStrategy":"type-guard","validationCode":"fn require_open(worker: &WorkerHandle) -> Result<(), &'static str> {\n    if worker.last_op_was_successful_open() { Ok(()) } else { Err(\"worker has no open database\") }\n}","typeGuard":"type OpenWorker = WorkerHandle;\nfn as_open(worker: &WorkerHandle) -> Option<&OpenWorker> {\n    worker.is_open().then_some(worker)\n}","tryCatchPattern":"match worker.send(WorkerOp::Query { sql, max_rows: None }).await {\n    Err(body) if body.error() == Some(\"SQLite worker has no open database\") => {\n        worker.send(WorkerOp::Open { path }).await?;\n        worker.send(WorkerOp::Query { sql, max_rows: None }).await?\n    }\n    other => other?,\n}","preventionTips":["Always Open before other ops; check the Open result","Track worker state client-side (opened/closed)","Reopen after Close or after any failed op","Encapsulate op sequences behind a helper that guarantees open-then-act"],"tags":["sqlite","worker","protocol","state","connection"],"backgroundTag":"no-open-database","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}