can1357/oh-my-pi · error · ValueError
Output {output_id} is not valid JSON: {e}
Error message
Output {output_id} is not valid JSON: {e} What it means
When `query` is passed to `output()`, the artifact content is first parsed with `json.loads`. This ValueError is raised when the `<id>.md` artifact is not valid JSON, wrapping the JSONDecodeError message so you know which output failed to parse. Artifacts may be plain text or ANSI-colored output, so a query is only valid against JSON artifacts.
Source
Thrown at packages/coding-agent/src/eval/py/prelude.py:219
output_path = Path(artifacts_dir) / f"{output_id}.md"
if not output_path.exists():
not_found.append(output_id)
continue
raw_content = output_path.read_text(encoding="utf-8")
raw_lines = raw_content.splitlines()
total_lines = len(raw_lines)
selected_content = raw_content
range_info: dict | None = None
# Handle query
if query:
try:
json_value = json.loads(raw_content)
except json.JSONDecodeError as e:
_emit_status("output", id=output_id, error=f"Not valid JSON: {e}")
raise ValueError(f"Output {output_id} is not valid JSON: {e}")
# Apply jq-like query
result_value = _apply_query(json_value, query)
try:
selected_content = (
json.dumps(result_value, indent=2)
if result_value is not None
else "null"
)
except (TypeError, ValueError):
selected_content = str(result_value)
# Handle offset/limit
elif offset is not None or limit is not None:
start_line = max(1, offset or 1)
if start_line > total_lines:
_emit_status(
"output",View on GitHub (pinned to 9690622007)
Solutions
- Read the artifact without `query` first (`output(["x"])`) and confirm/fix its JSON content.
- Remove the `query` and inspect the raw text, or slice with `offset`/`limit` instead.
- If the artifact should be JSON but is truncated/corrupted, re-run the producing tool call to regenerate the artifact.
Example fix
// before
data = output(["bash_1"], query=".files") # bash_1.md is plain text
// after
raw = output(["bash_1"])
if raw.lstrip().startswith("{"):
data = output(["bash_1"], query=".files")
else:
data = raw Defensive patterns
Strategy: validation
Validate before calling
import json
raw = output(["x"])
try:
json.loads(raw)
parsed = output(["x"], query=".result")
except json.JSONDecodeError:
parsed = None # artifact isn't JSON; handle as text Type guard
def is_json_artifact(raw: str) -> bool:
try:
json.loads(raw)
return True
except (json.JSONDecodeError, TypeError):
return False Try / catch
try:
data = output(["x"], query=".result")
except ValueError as e:
if "not valid JSON" in str(e):
data = output(["x"]) # fall back to raw content Prevention
- Only pass `query` when you know the producing tool emitted JSON.
- Pre-check artifacts with a cheap json.loads on a no-query read.
- Remember .md artifacts are often plain text or ANSI-colored output, not JSON.
When it happens
Trigger: Calling `output(ids=["x"], query=".result")` where `x.md` contains plain text, truncated output, ANSI escape sequences, or malformed JSON.
Common situations: Pointing a query at a bash-tool artifact that emitted plain text instead of JSON; querying an artifact whose JSON was truncated by an output cap; assuming all artifacts are JSON when only some tools emit JSON.
Related errors
- ${destination} returned invalid JSON
- At least one output ID is required
- query cannot be combined with offset/limit
- Offset {start_line} is beyond end of output ({total_lines} l
- Output not found: {', '.join(not_found)}\n\nAvailable output
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/66de863f974312a9.
Report an issue: GitHub.