Hmbown/CodeWhale · error · RuntimeError

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

Error message

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

What it means

The harness runs Codewhale with --output-format stream-json and parses stdout line by line as JSON events on the codewhale.exec-stream v0.9.1 schema. This error fires when a non-blank stdout line fails json.loads(), i.e. the binary wrote plain text where a JSON event was required. It is raised with the 1-based line number, wrapped as RuntimeError chaining the JSONDecodeError.

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 8880682c63)

Solutions

  1. Re-run the rollout capturing raw stdout (e.g. tee to a file) and look at the reported line number to see exactly what non-JSON text was emitted.
  2. Ensure every diagnostic from the binary or its wrapper goes to stderr, never stdout, when --output-format stream-json is active.
  3. Verify the installed binary matches CodewhaleHarnessConfig.version (default 0.9.1) and genuinely supports stream-json output.
  4. If binary_path points at a wrapper script, remove any echo/print to stdout so the only stdout content is JSON events.

Example fix

# before: wrapper prints to stdout
print(f"starting codewhale {VERSION}")  # pollutes stream-json
subprocess.run([binary, *args])

# after: diagnostics go to stderr
print(f"starting codewhale {VERSION}", file=sys.stderr)
subprocess.run([binary, *args])
Defensive patterns

Strategy: try-catch

Validate before calling

# Before handing stdout to the harness, sanity-check it line by line
import json

def stdout_is_ndjson(stdout: str) -> bool:
    return all(
        not line.strip() or _is_json_object(line)
        for line in stdout.splitlines()
    )

Type guard

def _is_json_object(line: str) -> bool:
    try:
        return isinstance(json.loads(line), dict)
    except json.JSONDecodeError:
        return False

Try / catch

try:
    receipt = _parse_stream_receipt(stdout)
except RuntimeError as error:
    line_no = re.search(r"line (\d+)", str(error))
    bad = stdout.splitlines()[int(line_no.group(1)) - 1] if line_no else "?"
    logger.error("unparseable stream line %r; stdout:\n%s", bad, stdout)
    raise

Prevention

When it happens

Trigger: Any non-JSON text on stdout: a facade printing a banner, warning, or log line; stderr leaking into the stdout pipe; a wrapper script around binary_path echoing shell noise; a Codewhale build that does not support stream-json output; partial output from a killed process leaving a truncated last line.

Common situations: Overriding CodewhaleHarnessConfig.binary_path with a local wrapper that prints extra output; running an old/new Codewhale version whose output format differs from the pinned 0.9.1; shell initialization (e.g. .bashrc echo) polluting stdout in the runtime; terminal escape codes or progress spinners written to fd 1.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/e2e1fd53eb36bb79. Report an issue: GitHub.