tinyhumansai/openhuman · error
{} worker protocol connection timed out
Error message
{} worker protocol connection timed out What it means
Establishing the protocol connection to a freshly spawned language-runtime worker timed out — the child process started, but it never completed the handshake (token exchange / readiness signal on stdout) within the allotted window. This fires when the worker binary is slow to boot (cold cache, heavy runtime init), hangs on startup (missing runtime dependencies, stuck module loading), or died without writing to stderr in a way the drain caught. The language id is interpolated into the message.
Source
Thrown at src/openhuman/runtime/pool/worker.rs:156
.spawn()
.with_context(|| format!("spawning {} worker", launch.lang.id()))?;
let child_stdin = child.stdin.take();
let stdout = child.stdout.take().context("worker stdout missing")?;
if let Some(stderr) = child.stderr.take() {
drain_stderr(launch.lang, stderr);
}
let (stdin, reader, expected_token): (
Box<dyn AsyncWrite + Send + Unpin>,
Box<dyn AsyncRead + Send + Unpin>,
Option<String>,
) = if let Some((listener, token)) = isolated_protocol {
// stdout is now exclusively user fd-level output. Drain it so
// chatty jobs cannot block; protocol frames use the socket.
drain_stdout(launch.lang, stdout);
let (stream, _) = tokio::time::timeout(HANDSHAKE_TIMEOUT, listener.accept())
.await
.map_err(|_| {
anyhow::anyhow!("{} worker protocol connection timed out", launch.lang.id())
})?
.context("accepting isolated worker protocol connection")?;
let (reader, writer) = tokio::io::split(stream);
(Box::new(writer), Box::new(reader), Some(token))
} else {
(
Box::new(child_stdin.context("worker stdin missing")?),
Box::new(stdout),
None,
)
};
let mut lines = BufReader::new(reader).lines();
let ready_line = match tokio::time::timeout(HANDSHAKE_TIMEOUT, lines.next_line()).await {
Ok(Ok(Some(line))) => line,
Ok(Ok(None)) => bail!(
"{} worker exited before readiness handshake",
launch.lang.id()View on GitHub (pinned to 7491200858)
Solutions
- Retry the operation — cold-start slowness often succeeds on a second attempt once caches are warm
- Check the worker runtime's dependencies are installed and its binary launches standalone
- For chronically slow starts, look for a configurable startup-timeout setting in the pool settings
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at src/openhuman/runtime/pool/worker.rs:156 when the library encounters an invalid state.
Common situations: See trigger scenarios.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/71d49bf3feddad47.
Report an issue: GitHub.