Hmbown/CodeWhale · error · RuntimeError
Codewhale stream-json line {line_number} was not an object
Error message
Codewhale stream-json line {line_number} was not an object What it means
Each non-blank stdout line from Codewhale must parse as JSON and then as a JSON object (dict). This error means the line was valid JSON but a scalar, array, or null — for example the string "42", "null", or a bare quoted string. It carries the offending line number so you can locate the exact event.
Source
Thrown at integrations/verifiers-codewhale/codewhale_harness/harness.py:359
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")
meta = event.get("meta")
if not isinstance(meta, dict) or meta.get("receipt_kind") != "terminal":
raise RuntimeError("Codewhale metadata event was not a terminal receipt")
terminal = _bounded_terminal(meta)View on GitHub (pinned to 8880682c63)
Solutions
- Inspect the reported line in the captured stdout to see which scalar/array the binary emitted.
- Make the producer wrap every line as an event object with schema, schema_version, and a known type field.
- Pin CodewhaleHarnessConfig.version to 0.9.1 or fix the custom binary_path facade to emit object events only.
- Move any scalar telemetry (counts, codes) into the metadata/done event payloads instead of standalone lines.
Example fix
# before: wrapper writes a scalar per line
sys.stdout.write(json.dumps(len(events)) + "\n")
# after: wrapper writes a well-formed event object
sys.stdout.write(json.dumps({"schema": "codewhale.exec-stream", "schema_version": 1, "type": "done"}) + "\n") Defensive patterns
Strategy: type-guard
Validate before calling
import json
def stream_lines_are_objects(stdout: str) -> bool:
for line in stdout.splitlines():
if not line.strip():
continue
value = json.loads(line) # raises on invalid JSON; check separately
if not isinstance(value, dict):
return False
return True Type guard
def is_stream_event(value: object) -> bool:
return (
isinstance(value, dict)
and value.get("schema") == "codewhale.exec-stream"
and value.get("schema_version") == 1
and isinstance(value.get("type"), str)
) Try / catch
except RuntimeError as error:
if "was not an object" in str(error):
# inspect the named line and fix the producer; do not retry blindly
log_stream_for_debug(stdout)
raise Prevention
- Emit only object events from facades; never bare json.dumps of scalars or arrays.
- Wrap scalar telemetry inside a well-typed event object.
- Add a facade unit test asserting every stdout line json.loads to a dict with the schema envelope.
When it happens
Trigger: A facade or Codewhale build emits JSON scalars on stdout: printing a token count, an exit code, or a JSON-encoded array where the harness expects one event object per line. Also happens when a wrapper json.dumps()s a non-dict value (str/int/list) into the stream.
Common situations: Custom binary_path wrappers that log values via json.dumps(value) instead of json.dumps(event_dict); versions of Codewhale that emit NDJSON status scalars; test stubs returning e.g. '"ok"' per line.
Related errors
- Codewhale stream-json line {line_number} was not valid JSON
- Codewhale terminal receipt exceeded its total bound
- Codewhale stream-json schema did not match v0.9.1
- Codewhale stream-json contained an unknown event type
- Codewhale emitted more than one terminal metadata receipt
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/eee7ebe3c1418d75.
Report an issue: GitHub.