{"record":{"id":"a70913c2b290d1a3","repo":"tinyhumansai/openhuman","slug":"claude-agent-sdk-error-from-claude-cli-err","errorCode":null,"errorMessage":"[claude_agent_sdk] error from claude CLI: {err}","messagePattern":"\\[claude_agent_sdk\\] error from claude CLI: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/inference/provider/claude_agent_sdk/subprocess.rs","lineNumber":227,"sourceCode":"\n        match read_result {\n            Ok(inner) => inner?,\n            Err(_) => {\n                let _ = child.kill().await;\n                anyhow::bail!(\"[claude_agent_sdk] subprocess timed out while reading output\");\n            }\n        }\n\n        let status = timeout(Duration::from_secs(30), child.wait())\n            .await\n            .map_err(|_| {\n                anyhow::anyhow!(\"[claude_agent_sdk] subprocess timed out while waiting for exit\")\n            })??;\n        let stderr_output = stderr_task.await.unwrap_or_default();\n        tracing::debug!(\"[claude_agent_sdk] subprocess exited status={}\", status);\n\n        if let Some(err) = error_message {\n            anyhow::bail!(\"[claude_agent_sdk] error from claude CLI: {err}\");\n        }\n\n        // Use the final result message if present; otherwise join streaming text parts.\n        let output = result_text\n            .filter(|s| !s.is_empty())\n            .unwrap_or_else(|| text_parts.join(\"\"));\n\n        if !status.success() && output.is_empty() {\n            anyhow::bail!(\n                \"[claude_agent_sdk] claude subprocess exited with non-zero status {} and no output; stderr={}\",\n                status,\n                stderr_output\n            );\n        }\n\n        tracing::debug!(\n            \"[claude_agent_sdk] response collected output_len={}\",\n            output.len()","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/inference/provider/claude_agent_sdk/subprocess.rs#L209-L245","documentation":"While draining the claude CLI's NDJSON stdout, the provider received an explicit error message from the CLI itself — either a `Result` message with `is_error: true` or a top-level `Error` event (subprocess.rs:172-193). The subprocess completed; the failure is semantic (the CLI's agent turn failed), not a process or transport failure. The CLI's own error text is appended to the message.","triggerScenarios":"The claude CLI returns an NDJSON result with `is_error` set (e.g. overloaded API, invalid request, credit/limit problem, disallowed tool use) or emits an `Error { message }` event. Any `chat` call routed to the claude_agent_sdk provider that ends in a CLI-side error.","commonSituations":"Anthropic API rate limits or 529 overloaded responses surfaced through the CLI, expired or invalid claude CLI login credentials, a prompt/request the CLI refuses (context overflow, forbidden tool), or quota exhaustion on the account.","solutions":["Read the `{err}` text — it is the CLI's verbatim reason (e.g. 'credit balance too low', 'rate_limit_error') and determines the fix.","For rate-limit/overload errors: retry with backoff; the failure is server-side and transient.","For auth errors: run `claude login` (or set the API key env the CLI uses) in the same user context as the core.","For request-shape errors (context too long): shrink the conversation or clear the session so the CLI starts a fresh context."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = provider.chat(req).await {\n    let msg = e.to_string();\n    if msg.contains(\"error from claude CLI\") {\n        // parse the trailing CLI text for rate_limit / credit / auth causes and branch\n        if msg.contains(\"rate_limit\") || msg.contains(\"overloaded\") {\n            backoff_retry(req).await;\n        } else {\n            surface_to_user(msg);\n        }\n    } else { return Err(e); }\n}","preventionTips":["Keep the CLI logged in (`claude login`) in the same user context as the core process.","Monitor quota/credits on the Anthropic account backing the CLI.","Trim long conversations to avoid CLI-side context-overflow refusals."],"tags":["claude-cli","agent-sdk","ndjson","inference"],"backgroundTag":"cli-agent-turn-failed","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}