Hmbown/CodeWhale · error · RuntimeError
Codewhale stream-json did not end with exactly one done even
Error message
Codewhale stream-json did not end with exactly one done event
What it means
The stream must terminate with exactly one done event and nothing after it: the harness checks counts['done'] == 1 and that the last entry in ordered_types is 'done'. This error fires when done is missing, emitted more than once, or when other events (even blank-skipped trailing noise parsed as events) follow it.
Source
Thrown at integrations/verifiers-codewhale/codewhale_harness/harness.py:382
) != 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)
if terminal is None:
raise RuntimeError("Codewhale stream-json omitted terminal metadata")
if counts["done"] != 1 or not ordered_types or ordered_types[-1] != "done":
raise RuntimeError("Codewhale stream-json did not end with exactly one done event")
if ordered_types[-2:-1] != ["metadata"]:
raise RuntimeError("Codewhale terminal metadata did not immediately precede done")
for field in ["binary_sha256", "prompt_sha256"]:
if not isinstance(terminal.get(field), str) or not _SHA256.fullmatch(
terminal[field]
):
raise RuntimeError(f"Codewhale terminal receipt omitted a valid {field}")
return {
"schema": STREAM_SCHEMA,
"schema_version": STREAM_SCHEMA_VERSION,
"events": dict(sorted(counts.items())),
"terminal": terminal,
}
View on GitHub (pinned to 8880682c63)
Solutions
- List ordered event types from captured stdout: verify the sequence ends with [..., 'metadata', 'done'] and contains exactly one 'done'.
- Remove any events emitted after done — done must be the final stdout line.
- Fix retry logic so only the final attempt emits done.
- Pin to Codewhale 0.9.1 or update the harness contract in lockstep with the facade changes.
Example fix
# before: wrapper appends a summary event after done
emit_done()
sys.stdout.write(json.dumps({"type": "content", "text": "summary"}) + "\n")
# after: done stays last
sys.stdout.write(json.dumps(summary_line) + "\n", file=sys.stderr) # or emit before done
emit_done() Defensive patterns
Strategy: validation
Validate before calling
def stream_ends_with_single_done(stdout: str) -> bool:
types = [
json.loads(line).get("type")
for line in stdout.splitlines()
if line.strip()
]
return types.count("done") == 1 and bool(types) and types[-1] == "done" Prevention
- Emit done exactly once, as the final stdout line, on success and failure paths alike.
- Never print events or wrappers after done.
- In retry loops, emit done only for the last attempt.
When it happens
Trigger: Zero done events (crash before completion), two done events (retry loops re-running the finalization), or events after done (a wrapper printing a summary line that parses as a valid event).
Common situations: Facades that wrap Codewhale and then print their own trailing event; binaries that emit done once per attempt; stdout fixtures where extra lines were appended after the terminator.
Related errors
- Codewhale terminal metadata did not immediately precede done
- Codewhale stream-json line {line_number} was not an object
- 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/a4c746b66d9fc583.
Report an issue: GitHub.