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

  1. Read the artifact without `query` first (`output(["x"])`) and confirm/fix its JSON content.
  2. Remove the `query` and inspect the raw text, or slice with `offset`/`limit` instead.
  3. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/66de863f974312a9. Report an issue: GitHub.