{"record":{"id":"33700f3b71058bc3","repo":"Hmbown/CodeWhale","slug":"codewhale-stream-json-contained-an-unknown-event-t","errorCode":null,"errorMessage":"Codewhale stream-json contained an unknown event type","messagePattern":"Codewhale stream-json contained an unknown event type","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"integrations/verifiers-codewhale/codewhale_harness/harness.py","lineNumber":368,"sourceCode":"        if not line.strip():\n            continue\n        try:\n            event = json.loads(line)\n        except json.JSONDecodeError as error:\n            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(","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/integrations/verifiers-codewhale/codewhale_harness/harness.py#L350-L386","documentation":"After the schema envelope check, the harness requires event['type'] to be one of ten known types: content, tool_use, tool_result, sandbox_denied, workflow_event, session_capture, turn_usage, metadata, done, error. This error means the event carried an unrecognized type string, which usually indicates the binary and harness disagree on the event vocabulary.","triggerScenarios":"A Codewhale build emits a new event type (e.g. a post-0.9.1 'thinking' or 'plan' event) that the harness's _EVENT_TYPES set does not include; or a facade writes a typo'd type like 'tool-use'. The stream is rejected even though the JSON and envelope were valid.","commonSituations":"Upgrading the Codewhale binary without updating the harness; using binary_path against a feature branch that added event types; hand-writing stream fixtures for tests with an invented type name.","solutions":["Capture stdout and list the distinct 'type' values; the failing one is not in {content, tool_use, tool_result, sandbox_denied, workflow_event, session_capture, turn_usage, metadata, done, error}.","Revert to the pinned Codewhale version 0.9.1 via CodewhaleHarnessConfig.version so the vocabulary matches.","If the new event type is legitimate, add it to _EVENT_TYPES in harness.py and update the harness contract tests in the same commit.","If the type is noise from a wrapper, remove that emission or route it to stderr."],"exampleFix":"# before: facade emits an unmapped type\n{\"schema\": \"codewhale.exec-stream\", \"schema_version\": 1, \"type\": \"thinking\", ...}\n\n# after: map it to a known type or teach the harness\n# (a) producer side: fold it into an existing type\n{\"schema\": \"codewhale.exec-stream\", \"schema_version\": 1, \"type\": \"content\", ...}\n# (b) harness side: _EVENT_TYPES.add(\"thinking\")","handlingStrategy":"validation","validationCode":"KNOWN_EVENT_TYPES = {\n    \"content\", \"tool_use\", \"tool_result\", \"sandbox_denied\",\n    \"workflow_event\", \"session_capture\", \"turn_usage\",\n    \"metadata\", \"done\", \"error\",\n}\n\ndef types_are_known(stdout: str) -> bool:\n    return all(\n        json.loads(line).get(\"type\") in KNOWN_EVENT_TYPES\n        for line in stdout.splitlines()\n        if line.strip()\n    )","typeGuard":"def is_known_event(event: object) -> bool:\n    return isinstance(event, dict) and event.get(\"type\") in KNOWN_EVENT_TYPES","tryCatchPattern":null,"preventionTips":["Upgrade harness and binary together so _EVENT_TYPES matches the producer's vocabulary.","When adding a producer event type, extend _EVENT_TYPES in the same change with tests.","Prefer mapping new signals onto existing types (content/error/workflow_event) before minting new ones."],"tags":["schema","version-skew","validation","stream-json","codewhale-harness"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}