t8y2/dbx · error · DuckDbWorkerError
invalid_json
invalid_json
Error message
Invalid worker request JSON: {err} What it means
run_stdio_worker reads newline-delimited JSON requests from stdin and parses them with serde_json; any malformed line yields an invalid_json error response (with empty request id) that is written back to stdout, and processing continues. The error message embeds the serde error describing exactly what was wrong.
Solutions
- Log the offending line and compare against the DuckDbWorkerRequest schema expected by the worker binary; align host and worker versions.
- Ensure each request is written as exactly one complete JSON object followed by a newline, and flush after each write.
- Validate/serialize requests with the same serde types (or the generated bindings) instead of hand-building JSON strings.
Example fix
// before
stdin.write(`{"id":1,"method":execute}`); // invalid JSON, unquoted method
// after
const req = JSON.stringify({ id: "1", method: "execute", params: {} });
stdin.write(req + "\n"); Defensive patterns
Strategy: validation
Validate before calling
// TS: validate before writing to the worker's stdin
const req = { id, method, params };
const line = JSON.stringify(req);
JSON.parse(line); // throws locally if serialization is broken
workerStdin.write(line + "\n"); Type guard
function isValidRequest(r: unknown): r is DuckDbWorkerRequest {
return typeof r === "object" && r !== null
&& typeof (r as any).id === "string"
&& typeof (r as any).method === "string";
} Try / catch
if (response.error?.code === "invalid_json") {
console.error("request rejected:", response.error.message);
// fix serializer / version-align host and worker, then resend
} Prevention
- Always serialize requests with JSON.stringify from typed objects, never hand-built strings.
- Write one complete JSON object per line and flush after each write.
- Keep host and worker protocol schemas/version in lockstep.
When it happens
Trigger: Writing a line to the worker's stdin (runtime.rs:440) that is not a valid DuckDbWorkerRequest JSON: truncated output, wrong field names/types, duplicate fields, or non-UTF8/binary garbage on the pipe.
Common situations: Host and worker binary version mismatch (schema drift in DuckDbWorkerRequest); host writing partial JSON due to a pipe buffering bug; a parent process flushing logs/JSON into the same stdin; console noise injected into the protocol stream.
Related errors
- duckdb_worker_exited
- encode subscription group config
- Failed to migrate JSON data
- Failed to migrate JSON data
- is required
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/38b606114a143bf7.
Report an issue: GitHub.
Appendix: source
Thrown at agents/drivers/duckdb/src/runtime.rs:440
let line = lines.next_line().await.map_err(|e| e.to_string())?;
let Some(line) = line else {
// Parent closed stdin (exit or crash). Idle workers checkpoint and
// remove their WAL on the normal return path; a worker still running
// a query must not wait for it (nor drop a poisoned connection),
// so it keeps the legacy immediate exit and the WAL replays on the
// next open.
if !runtime.close_session_for_shutdown() {
std::process::exit(0);
}
break;
};
if line.trim().is_empty() {
continue;
}
let request: DuckDbWorkerRequest = match serde_json::from_str(&line) {
Ok(request) => request,
Err(err) => {
let response = DuckDbWorkerResponse::err(
"",
DuckDbWorkerError::new("invalid_json", format!("Invalid worker request JSON: {err}")),
);
write_response(stdout.clone(), &response).await;
continue;
}
};
let result = runtime.handle_request(request, stdout.clone()).await;
if let Some(response) = result.response {
write_response(stdout.clone(), &response).await;
}
if result.shutdown {
break;
}
}
Ok(())
}
View on GitHub (pinned to c0390bff16)