{"record":{"id":"d41a6e9b239d1370","repo":"t8y2/dbx","slug":"duckdb-worker-busy","errorCode":"duckdb_worker_busy","errorMessage":"DuckDB worker is already executing a query","messagePattern":"DuckDB worker is already executing a query","errorType":"error_code","errorClass":"DuckDbWorkerError","httpStatus":null,"severity":"error","filePath":"agents/drivers/duckdb/src/runtime.rs","lineNumber":288,"sourceCode":"                let params = request.parse_params()?;\n                Ok(DuckDbWorkerResponse::ok(request.id, session.get_table_ddl(params)?))\n            }),\n            DuckDbWorkerMethod::CompletionAssistant => self.handle_session_request(request, |session, request| {\n                let params = request.parse_params()?;\n                Ok(DuckDbWorkerResponse::ok(request.id, session.completion_assistant(params)?))\n            }),\n            DuckDbWorkerMethod::GetObjectSource => self.handle_session_request(request, |session, request| {\n                let params = request.parse_params()?;\n                Ok(DuckDbWorkerResponse::ok(request.id, session.get_object_source(params)?))\n            }),\n            DuckDbWorkerMethod::AttachDatabase => self.handle_session_request(request, |session, request| {\n                session.attach_database(request.parse_params()?)?;\n                Ok(DuckDbWorkerResponse::ok_empty(request.id))\n            }),\n            DuckDbWorkerMethod::Execute => {\n                if self.active_interrupt.lock().unwrap_or_else(|e| e.into_inner()).is_some() {\n                    return WorkerHandleResult {\n                        response: Some(DuckDbWorkerResponse::err(\n                            request.id,\n                            DuckDbWorkerError::new(\"duckdb_worker_busy\", \"DuckDB worker is already executing a query\"),\n                        )),\n                        shutdown: false,\n                    };\n                }\n\n                let interrupt_handle = match self.session.lock().unwrap_or_else(|e| e.into_inner()).interrupt_handle() {\n                    Ok(handle) => handle,\n                    Err(err) => {\n                        return WorkerHandleResult {\n                            response: Some(DuckDbWorkerResponse::err(\n                                request.id,\n                                DuckDbWorkerError::from_message(\"duckdb_not_connected\", err),\n                            )),\n                            shutdown: false,\n                        }\n                    }","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/duckdb/src/runtime.rs#L270-L306","documentation":"The DuckDB worker's Execute method rejects incoming queries while an interrupt is flagged, i.e. the worker is still executing a previous query. DuckDB operations are not reentrant in this worker, so a second Execute arriving mid-run returns a duckdb_worker_busy error response instead of being processed.","triggerScenarios":"Sending a DuckDbWorkerMethod::Execute request (runtime.rs:288) while active_interrupt is Some — a prior query is still running or its interrupt/cancel flag was not cleared, often when the client pipelines queries without awaiting responses.","commonSituations":"Frontend issuing a new query while a long-running one executes; a cancelled query leaving active_interrupt set; race between interrupt handling and the next request.","solutions":["Serialize queries client-side: await the response (or the resolved promise) before sending the next Execute request.","Wait for or clear the active interrupt state before issuing the next query; if a previous cancel wedged, recycle the worker process.","Queue requests in a driver-level mutex/semaphore so concurrency never reaches the worker while busy."],"exampleFix":"// before\nvoid runQuery(sql); runQuery(sql2);\n// after\nconst busy = await isWorkerBusy();\nif (busy) await waitUntilIdle();\nawait runQuery(sql);\nawait runQuery(sql2);","handlingStrategy":"retry","validationCode":"// TS: check busy state before dispatching\nasync function canExecute(worker: DuckDbWorker): Promise<boolean> {\n  return !(await worker.getInterruptFlag());\n}","typeGuard":"function isBusyError(e: unknown): e is { code: \"duckdb_worker_busy\" } {\n  return typeof e === \"object\" && e !== null && (e as any).code === \"duckdb_worker_busy\";\n}","tryCatchPattern":"try {\n  await worker.execute(sql);\n} catch (e) {\n  if (isBusyError(e)) {\n    await worker.waitForIdle();\n    return worker.execute(sql);\n  }\n  throw e;\n}","preventionTips":["Await each query's response before sending the next Execute.","Route all queries through a single-flight queue/mutex per worker.","After a cancel, wait for the interrupt flag to clear before new requests."],"tags":["rust","duckdb","concurrency","worker"],"backgroundTag":"worker-busy","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}