Graphify-Labs/graphify · error · RuntimeError
claude -p produced unparseable JSON envelope: {exc}; first 5
Error message
claude -p produced unparseable JSON envelope: {exc}; first 500 chars of stdout: {stdout[:500]!r} What it means
Raised by `_claude_cli_envelope` when `json.loads(stdout)` fails on the output of `claude -p --output-format json`. graphify expects the CLI's stdout to be a single JSON object (older CLIs) or a JSON array of streamed events (newer CLIs ≥ ~2.1); anything unparseable — interleaved warnings, banners, partial writes — triggers this error, including the first 500 chars of what was actually received to aid diagnosis.
Source
Thrown at graphify/llm.py:1365
file=sys.stderr,
)
result["finish_reason"] = "length"
return result
def _claude_cli_envelope(stdout: str) -> dict:
"""Parse the JSON returned by `claude -p --output-format json`.
Older Claude Code CLI versions returned a single envelope object. Newer
versions (>= ~2.1) emit a JSON ARRAY of streamed event objects (a system
init event, assistant turns, an optional rate_limit_event, and a final
{"type":"result"} object). Normalize both shapes to the result dict that
carries `result`, `usage`, `modelUsage`, and `stop_reason`.
"""
try:
envelope = json.loads(stdout)
except json.JSONDecodeError as exc:
raise RuntimeError(
f"claude -p produced unparseable JSON envelope: {exc}; "
f"first 500 chars of stdout: {stdout[:500]!r}"
) from exc
if isinstance(envelope, list):
result_events = [
e for e in envelope
if isinstance(e, dict) and e.get("type") == "result"
]
if result_events:
return result_events[-1]
if envelope and isinstance(envelope[-1], dict):
return envelope[-1]
raise RuntimeError(
"claude -p returned a JSON array with no result object; "
f"first 500 chars of stdout: {stdout[:500]!r}"
)
return envelope
View on GitHub (pinned to 7fe58b0b0f)
Solutions
- Update Claude Code CLI to a current version (`claude update` or reinstall via npm) — the envelope formats supported cover recent releases.
- Run `claude -p --output-format json "hi"` manually and confirm stdout is pure JSON; if not, find what is polluting it (shell profile banners, plugins, progress bars).
- Authenticate first: run `claude` once interactively so the headless `-p` mode doesn't emit login prose.
- If the run timed out, raise GRAPHIFY_API_TIMEOUT / --api-timeout so the full envelope is flushed.
Defensive patterns
Strategy: validation
Validate before calling
import json, subprocess
def claude_cli_emits_json() -> bool:
p = subprocess.run(["claude", "-p", "--output-format", "json", "say ok"],
capture_output=True, text=True, timeout=60)
try:
json.loads(p.stdout)
return True
except json.JSONDecodeError:
return False
assert claude_cli_emits_json(), "claude CLI stdout is not pure JSON; update/reinstall the CLI" Try / catch
try:
result = extract_files_direct(files, root, backend="claude-cli")
except RuntimeError as e:
if "unparseable JSON envelope" in str(e):
print(f"CLI stdout corrupted: {e}"); raise
raise Prevention
- Pin a known-good Claude Code CLI version in CI.
- Run `claude` once interactively to authenticate before headless use.
- Keep shell profiles/plugins from printing banners into stdout of subprocess pipelines.
When it happens
Trigger: Running the `claude-cli` backend where `claude -p` writes non-JSON to stdout: a CLI version with a changed output format, ANSI/progress output mixed into stdout, a truncated run killed by the subprocess timeout, or plugin/startup messages the CLI prints before the JSON envelope.
Common situations: Upgrading (or pinning an old) Claude Code CLI whose output format graphify doesn't recognize; running in a terminal/wrapper that appends text to stdout; `claude` not authenticated so it prints a login prompt instead of JSON; stdout truncated when the process hits the `_resolve_api_timeout()` bound.
Related errors
- claude -p returned a JSON array with no result object; first
- Claude Code CLI not found on $PATH. Install from https://cla
- claude -p exited {proc.returncode}: {detail[:500]}
- label response is not parseable JSON: {text[:120]!r}
- tree-sitter is not installed. Run: pip install 'tree-sitter>
AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14).
Data as JSON: /api/errors/d814b6986357b59e.
Report an issue: GitHub.