{"record":{"id":"5ba97bb18ae42d5e","repo":"Hmbown/CodeWhale","slug":"codewhale-emitted-more-than-one-terminal-metadata","errorCode":null,"errorMessage":"Codewhale emitted more than one terminal metadata receipt","messagePattern":"Codewhale emitted more than one terminal metadata receipt","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"integrations/verifiers-codewhale/codewhale_harness/harness.py","lineNumber":373,"sourceCode":"            raise RuntimeError(\n                f\"Codewhale stream-json line {line_number} was not valid JSON\"\n            ) from error\n        if not isinstance(event, dict):\n            raise RuntimeError(\n                f\"Codewhale stream-json line {line_number} was not an object\"\n            )\n        if event.get(\"schema\") != STREAM_SCHEMA or event.get(\n            \"schema_version\"\n        ) != STREAM_SCHEMA_VERSION:\n            raise RuntimeError(\"Codewhale stream-json schema did not match v0.9.1\")\n        event_type = event.get(\"type\")\n        if event_type not in _EVENT_TYPES:\n            raise RuntimeError(\"Codewhale stream-json contained an unknown event type\")\n        counts[event_type] += 1\n        ordered_types.append(event_type)\n        if event_type == \"metadata\":\n            if terminal is not None:\n                raise RuntimeError(\"Codewhale emitted more than one terminal metadata receipt\")\n            meta = event.get(\"meta\")\n            if not isinstance(meta, dict) or meta.get(\"receipt_kind\") != \"terminal\":\n                raise RuntimeError(\"Codewhale metadata event was not a terminal receipt\")\n            terminal = _bounded_terminal(meta)\n\n    if terminal is None:\n        raise RuntimeError(\"Codewhale stream-json omitted terminal metadata\")\n    if counts[\"done\"] != 1 or not ordered_types or ordered_types[-1] != \"done\":\n        raise RuntimeError(\"Codewhale stream-json did not end with exactly one done event\")\n    if ordered_types[-2:-1] != [\"metadata\"]:\n        raise RuntimeError(\"Codewhale terminal metadata did not immediately precede done\")\n    for field in [\"binary_sha256\", \"prompt_sha256\"]:\n        if not isinstance(terminal.get(field), str) or not _SHA256.fullmatch(\n            terminal[field]\n        ):\n            raise RuntimeError(f\"Codewhale terminal receipt omitted a valid {field}\")\n    return {\n        \"schema\": STREAM_SCHEMA,","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/integrations/verifiers-codewhale/codewhale_harness/harness.py#L355-L391","documentation":"The stream-json contract allows exactly one terminal metadata receipt. The harness keeps the first metadata event's bounded receipt in `terminal`; when a second metadata event arrives while terminal is already set, it raises this error instead of silently overwriting usage/token/hash data.","triggerScenarios":"A Codewhale binary emits two metadata events with meta.receipt_kind == 'terminal' — e.g. one mid-run (progress snapshot) and one at the end, or a retry loop that re-emits the final receipt. Any second qualifying metadata event triggers it, even if the first was not adjacent to done.","commonSituations":"Facades that emit periodic metadata checkpoints but label all of them receipt_kind='terminal'; a resume/retry path in the binary that prints the receipt twice; test fixtures that naively append a metadata event at both start and end.","solutions":["Grep the captured stdout for '\"type\": \"metadata\"' and confirm there are two terminal receipts.","Emit exactly one terminal metadata event, immediately before the done event.","Label any non-terminal metadata (progress, partial usage) with a different receipt_kind so the harness ignores it as a terminal candidate — note that then it must not be the [-2] event, which must be the terminal one.","If two receipts are genuinely needed, extend the harness contract explicitly rather than reusing 'terminal'."],"exampleFix":"# before: checkpoint metadata reuses the terminal kind\nemit({\"type\": \"metadata\", \"meta\": {\"receipt_kind\": \"terminal\", ...}})\n...\nemit({\"type\": \"metadata\", \"meta\": {\"receipt_kind\": \"terminal\", ...}})\n\n# after: only the final receipt is terminal\nemit({\"type\": \"metadata\", \"meta\": {\"receipt_kind\": \"progress\", ...}})\n...\nemit({\"type\": \"metadata\", \"meta\": {\"receipt_kind\": \"terminal\", ...}})","handlingStrategy":"validation","validationCode":"def has_single_terminal_metadata(stdout: str) -> bool:\n    n = 0\n    for line in stdout.splitlines():\n        if not line.strip():\n            continue\n        event = json.loads(line)\n        if event.get(\"type\") == \"metadata\":\n            meta = event.get(\"meta\")\n            if isinstance(meta, dict) and meta.get(\"receipt_kind\") == \"terminal\":\n                n += 1\n    return n == 1","typeGuard":"def is_terminal_metadata(event: object) -> bool:\n    return (\n        isinstance(event, dict)\n        and event.get(\"type\") == \"metadata\"\n        and isinstance(event.get(\"meta\"), dict)\n        and event[\"meta\"].get(\"receipt_kind\") == \"terminal\"\n    )","tryCatchPattern":null,"preventionTips":["Emit exactly one terminal metadata event per run, as the penultimate stdout line.","Use a different receipt_kind for progress/partial metadata so it is never mistaken for terminal.","In facade tests, assert the metadata-with-terminal count over recorded runs equals 1."],"tags":["metadata","validation","stream-json","codewhale-harness","duplicate"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}