Hmbown/CodeWhale · error · RuntimeError
Codewhale stream-json line
Error message
Codewhale stream-json line {line_number} was not an object What it means
Each parsed stream-json line must be a JSON object (dict); arrays, strings, or bare numbers are rejected. This RuntimeError means line N parsed as JSON but was not an object, so the harness cannot read its schema/type fields. It throws immediately because the event stream contract is objects only.
Solutions
- Inspect stdout line N to see the non-object JSON value
- Fix the emitter to write exactly one JSON object per line
- Replace any relay/wrapper that batches events into an array with per-line object emission
- Pin to the official Codewhale release that honors --output-format stream-json object semantics
Example fix
// before (emitter)
[{"schema":"..."},{"schema":"..."}]
// after
{"schema":"..."}
{"schema":"..."} Defensive patterns
Strategy: validation
Validate before calling
def lines_are_objects(stdout: str) -> bool:
import json
for line in stdout.splitlines():
if not line.strip():
continue
if not isinstance(json.loads(line), dict):
return False
return True Type guard
def is_event(value: object) -> bool:
return isinstance(value, dict) and "type" in value Try / catch
try:
result = await harness.launch(ctx, trace, runtime, endpoint, secret, mcp_urls)
except RuntimeError as e:
if "was not an object" in str(e):
logger.error("stream emitted non-object JSON; fix emitter framing")
raise Prevention
- Emit exactly one JSON object per line; never batch into arrays
- Add a framing test to any emitter/relay that converts stdout to events
- Pin binary versions so framing semantics cannot drift silently
- Validate a sample stream fixture with the harness before production rollouts
When it happens
Trigger: _parse_stream_receipt read a line where json.loads succeeded but isinstance(event, dict) was False — e.g. a line containing '[...]' or 'null' or a quoted string from a misbehaving emitter.
Common situations: A patched Codewhale or relay emitting JSON arrays of events instead of one object per line; log forwarders pretty-printing lists; test doubles writing raw values instead of event objects.
Related errors
- Cargo metadata is not valid JSON
- Codewhale stream-json line
- credential file must be a JSON object of entries
- Failed to parse Ollama /api/tags JSON
- Invalid JSON on nonempty line
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/eee7ebe3c1418d75.
Report an issue: GitHub.
Appendix: 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 433685b202)