Hmbown/CodeWhale · error · RuntimeError

Codewhale stream-json line

Error message

Codewhale stream-json line {line_number} was not valid JSON

What it means

Codewhale emits its run log as newline-delimited JSON (stream-json) on stdout, and every non-blank line must parse as JSON. This RuntimeError, chained from json.JSONDecodeError, means line N of the program's stdout was not valid JSON. The harness throws it immediately because partial/corrupt stream output means the receipt cannot be trusted.

Solutions

  1. Capture and inspect the raw stdout around the reported line_number to see what was printed
  2. Remove wrappers/shell rc files that echo text when the binary runs (check binary_path)
  3. Upgrade or pin Codewhale to the 0.9.1 release whose --output-format stream-json is clean
  4. Ensure NO_COLOR=1 and --telemetry false reach the binary so no decorated lines are emitted
  5. If you control the emitter, direct human logs to stderr and keep stdout strictly NDJSON

Example fix

// before (emitting binary)
printf("starting run...\n");  // stdout
// after
fprintf(stderr, "starting run...\n");
Defensive patterns

Strategy: try-catch

Validate before calling

import json
def stdout_is_ndjson(stdout: str) -> bool:
    return all(
        (not line.strip()) or _is_json(line)
        for line in stdout.splitlines()
    )
def _is_json(line: str) -> bool:
    try:
        json.loads(line); return True
    except json.JSONDecodeError:
        return False

Try / catch

try:
    result = await harness.launch(ctx, trace, runtime, endpoint, secret, mcp_urls)
except RuntimeError as e:
    if "was not valid JSON" in str(e):
        logger.error("non-NDJSON on stdout; check wrappers and stderr discipline")
    raise

Prevention

When it happens

Trigger: _parse_stream_receipt iterated result.stdout after a zero exit code and json.loads failed on a line — e.g. human-readable log text, progress bars, warnings, or a crash message interleaved with the stream.

Common situations: A wrapper binary or shell profile printing banners to stdout; a pre-release binary writing plain-text logs; NO_COLOR/telemetry settings not honored; output corruption from pipes or encoding issues.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/e2e1fd53eb36bb79. Report an issue: GitHub.

Appendix: source

Thrown at integrations/verifiers-codewhale/codewhale_harness/harness.py:355

done
(cd "$install_dir/bin" && sha256sum codewhale codew codewhale-tui > .sha256.tmp)
mv -f "$install_dir/bin/.sha256.tmp" "$install_dir/bin/.sha256"
printf '%s' "$version" > "$install_dir/bin/.version.tmp"
mv -f "$install_dir/bin/.version.tmp" "$install_dir/bin/.version"
"""


def _parse_stream_receipt(stdout: str) -> dict[str, Any]:
    counts: Counter[str] = Counter()
    terminal: dict[str, Any] | None = None
    ordered_types: list[str] = []
    for line_number, line in enumerate(stdout.splitlines(), start=1):
        if not line.strip():
            continue
        try:
            event = json.loads(line)
        except json.JSONDecodeError as error:
            raise RuntimeError(
                f"Codewhale stream-json line {line_number} was not valid JSON"
            ) from error
        if not isinstance(event, dict):
            raise RuntimeError(
                f"Codewhale stream-json line {line_number} was not an object"
            )
        if event.get("schema") != STREAM_SCHEMA or event.get(
            "schema_version"
        ) != STREAM_SCHEMA_VERSION:
            raise RuntimeError("Codewhale stream-json schema did not match v0.9.1")
        event_type = event.get("type")
        if event_type not in _EVENT_TYPES:
            raise RuntimeError("Codewhale stream-json contained an unknown event type")
        counts[event_type] += 1
        ordered_types.append(event_type)
        if event_type == "metadata":
            if terminal is not None:
                raise RuntimeError("Codewhale emitted more than one terminal metadata receipt")

View on GitHub (pinned to 433685b202)