tinyhumansai/openhuman · error · anyhow::Error
[claude_agent_sdk] subprocess timed out while reading output
Error message
[claude_agent_sdk] subprocess timed out while reading output
What it means
The claude_agent_sdk provider spawns the `claude` CLI as a child process and reads NDJSON messages from its stdout under a 120-second tokio timeout (subprocess.rs:158). This error fires when that outer timeout elapses before stdout reaches EOF — i.e. the CLI produced no complete output stream within 2 minutes. The child is explicitly killed before bailing, so no orphan process remains.
Source
Thrown at src/openhuman/inference/provider/claude_agent_sdk/subprocess.rs:214
}
Err(e) => {
tracing::warn!(
error = %e,
line_len = line.len(),
"[claude_agent_sdk] failed to parse ndjson line"
);
}
}
}
anyhow::Ok(())
})
.await;
match read_result {
Ok(inner) => inner?,
Err(_) => {
let _ = child.kill().await;
anyhow::bail!("[claude_agent_sdk] subprocess timed out while reading output");
}
}
let status = timeout(Duration::from_secs(30), child.wait())
.await
.map_err(|_| {
anyhow::anyhow!("[claude_agent_sdk] subprocess timed out while waiting for exit")
})??;
let stderr_output = stderr_task.await.unwrap_or_default();
tracing::debug!("[claude_agent_sdk] subprocess exited status={}", status);
if let Some(err) = error_message {
anyhow::bail!("[claude_agent_sdk] error from claude CLI: {err}");
}
// Use the final result message if present; otherwise join streaming text parts.
let output = result_text
.filter(|s| !s.is_empty())View on GitHub (pinned to 7491200858)
Solutions
- Retry the request — transient CLI/network stalls are the most common cause and a fresh turn often completes.
- Check the core debug log for `[claude_agent_sdk]` lines: if the last NDJSON line arrived recently, the turn was genuinely long; consider raising the 120s timeout in subprocess.rs:158 to fit your workload.
- Run `claude --version` and update the CLI; older builds hang on permission/trust prompts in non-interactive mode.
- Audit configured MCP servers (`claude mcp list`) for a server that never completes its handshake and stalls the turn.
Example fix
// before
let read_result = timeout(Duration::from_secs(120), async { /* read stdout */ }).await;
// after — size the deadline to the workload (long agentic turns)
let read_result = timeout(Duration::from_secs(600), async { /* read stdout */ }).await; Defensive patterns
Strategy: retry
Validate before calling
// Rust — pre-flight the CLI before routing long turns to it
async fn claude_sdk_ready() -> bool {
tokio::process::Command::new("claude")
.arg("--version")
.output()
.await
.map(|o| o.status.success())
.unwrap_or(false)
} Try / catch
match provider.chat(req).await {
Err(e) if e.to_string().contains("timed out while reading output") => {
// transient stall: retry once with backoff, then surface to user
tokio::time::sleep(Duration::from_secs(3)).await;
provider.chat(req).await
}
other => other,
} Prevention
- Keep the claude CLI updated so it never blocks on interactive prompts in non-interactive mode.
- Audit MCP servers used by the CLI for hanging tools before routing automated turns.
- Size expectations: turns regularly exceeding 120s need a raised read timeout in subprocess.rs.
When it happens
Trigger: A `claude` SDK-mode request where the CLI hangs: a very long-running agentic turn exceeding 120s, a CLI waiting on a stuck MCP server or permission prompt, a deadlocked stdin pipe, or a network stall between the CLI and Anthropic APIs. Triggered by the `Err(_elapsed)` arm of `timeout(Duration::from_secs(120), ...)` around the stdout line-reading loop.
Common situations: Long agent turns (tool-heavy sessions routinely exceed 2 minutes), corporate proxies that stall the CLI's HTTPS connection, a claude CLI version that blocks on interactive trust prompts when run non-interactively, or an MCP server configured in the project that never responds.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- [claude_agent_sdk] error from claude CLI: {err}
- [claude_agent_sdk] claude subprocess exited with non-zero st
- [claude-code][driver] turn timed out after {:?}
- oauthAuthReadinessUserMessage(quick.reason)
- Model testing is only available in the desktop app.
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/1b577b441cfa186c.
Report an issue: GitHub.