JuliusBrussee/caveman · error · RuntimeError
Claude call failed: {e.stderr}
Error message
Claude call failed:
{e.stderr} What it means
Raised by compress_file's Claude-call helper in the caveman-compress skill when `claude --print` exits nonzero (subprocess.CalledProcessError). The subprocess runs with check=True, capture_output=True, so any nonzero exit — auth failure, rate limit, network error, invalid model config — surfaces here with the child's stderr appended to the message.
Source
Thrown at skills/caveman-compress/scripts/compress.py:223
# Resolve binary via shutil.which so Windows .cmd/.bat shims (e.g.
# %APPDATA%\npm\claude.CMD) work without shell=True. On POSIX,
# shutil.which returns the same absolute path as the implicit lookup,
# so this is a no-op there. Falls back to bare "claude" if not found
# on PATH so subprocess raises a clear FileNotFoundError.
claude_bin = shutil.which("claude") or "claude"
try:
result = subprocess.run(
[claude_bin, "--print"],
input=prompt,
text=True,
capture_output=True,
check=True,
encoding="utf-8",
errors="replace",
)
return strip_llm_wrapper(result.stdout.strip())
except subprocess.CalledProcessError as e:
raise RuntimeError(f"Claude call failed:\n{e.stderr}")
def build_compress_prompt(original: str) -> str:
return f"""
Compress this markdown into caveman format.
STRICT RULES:
- Do NOT modify anything inside ``` code blocks
- Do NOT modify anything inside inline backticks
- Preserve ALL URLs exactly
- Preserve ALL headings exactly
- Preserve file paths and commands
- Return ONLY the compressed markdown body — do NOT wrap the entire output in a ```markdown fence or any other fence. Inner code blocks from the original stay as-is; do not add a new outer fence around the whole file.
Only compress natural language.
TEXT:
{original}View on GitHub (pinned to 27d5a3981a)
Solutions
- Read the stderr embedded in the message — it is the claude CLI's own error and names the real cause (auth, quota, network).
- Run `claude --print` manually with a trivial prompt (echo hi | claude --print) to reproduce and confirm auth/network works.
- Re-authenticate (claude login / set API key) or wait out the rate limit, then retry the compress command.
- Verify the claude binary is on PATH and up to date if stderr shows a usage/flag error (which claude; claude --version).
Defensive patterns
Strategy: try-catch
Validate before calling
import shutil, subprocess
def claude_cli_ready() -> bool:
if shutil.which("claude") is None:
return False
return subprocess.run(["claude", "--print"], input="ping",
capture_output=True, text=True).returncode == 0 Try / catch
try:
compress_file(path)
except RuntimeError as e:
if "Claude call failed" in str(e):
# e's tail is the CLI's own stderr: auth/quota/network — fix that, then retry once
diagnose_and_retry_once(e)
raise Prevention
- Run `claude --print` once with a trivial prompt before starting a batch compress job.
- Keep the claude CLI authenticated and updated; check `claude --version` after upgrades.
- Wrap batch loops so one failed call logs the stderr and stops instead of hammering a rate-limited endpoint.
When it happens
Trigger: Running compress.py (file/URL/text condense flows) when the local `claude` CLI is not authenticated, the API key is missing/expired, the account is rate-limited or out of credits, the network is down, or the claude binary version rejects the `--print` invocation.
Common situations: First run on a new machine before `claude` login; expired OAuth session in the CLI; corporate proxy blocking api.anthropic.com; free-tier quota exhausted mid-batch while compressing many files.
Related errors
- empty version output
- cache-replay: verifier process failed
- Claude usage request failed with HTTP %d
- cave_harness_request_invalid
- cave_eve_terminal_${result.status}
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/ff3eef3624937621.
Report an issue: GitHub.