{"record":{"id":"43cfe1613822b449","repo":"Hmbown/CodeWhale","slug":"unrecognized-sse-event-e","errorCode":null,"errorMessage":"unrecognized SSE event: {e}","messagePattern":"unrecognized SSE event: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/client/anthropic.rs","lineNumber":817,"sourceCode":"        Some(known)\n            if !matches!(\n                known,\n                \"message_start\"\n                    | \"content_block_start\"\n                    | \"content_block_delta\"\n                    | \"content_block_stop\"\n                    | \"message_delta\"\n                    | \"message_stop\"\n                    | \"ping\"\n                    | \"error\"\n            ) =>\n        {\n            return None;\n        }\n        _ => {}\n    }\n\n    Some(serde_json::from_value(value).map_err(|e| anyhow::anyhow!(\"unrecognized SSE event: {e}\")))\n}\n\n/// Map Anthropic's usage payload onto the normalized [`Usage`] convention\n/// (#2961 / #4318): hit = cache reads, write = cache creation, miss = raw\n/// uncached input, `input_tokens` = the total prompt across all three.\nfn parse_anthropic_usage(usage: &Value) -> Usage {\n    let field = |name: &str| {\n        usage\n            .get(name)\n            .and_then(Value::as_u64)\n            .and_then(|value| u32::try_from(value).ok())\n            .unwrap_or(0)\n    };\n    let input_raw = field(\"input_tokens\");\n    let cache_creation = field(\"cache_creation_input_tokens\");\n    let cache_read = field(\"cache_read_input_tokens\");\n    let output = field(\"output_tokens\");\n","sourceCodeStart":799,"sourceCodeEnd":835,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/client/anthropic.rs#L799-L835","documentation":"The SSE payload parsed as JSON, but its `type` was not in the ignorable list (`message_start`, `content_block_*`, `message_delta`, `message_stop`, `ping`, `error`), so the client deserialized it into its `StreamEvent` models — and that failed. This is schema drift: Anthropic emitted an event shape the client does not know, and the client fails closed rather than guess.","triggerScenarios":"Anthropic ships a new SSE event type or renames/re-types a field while the client's `StreamEvent` structs are older; a beta feature emits events outside the mapped set.","commonSituations":"Running an outdated build of the client against a live API that has evolved; opting into Anthropic beta features whose events are newer than the client's models.","solutions":["Update the crate/TUI to the latest version — new event mappings are added as Anthropic ships them","Check the Anthropic changelog for new streaming event types matching the serde error text","Capture the failing payload and, for a local build, add a match arm returning `None` for the ignorable new type or a proper mapping","Retry on the updated build; do not retry unchanged — the same event will fail again"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_unrecognized_sse_event(err: &anyhow::Error) -> bool {\n    err.to_string().starts_with(\"unrecognized SSE event\")\n}","tryCatchPattern":"match stream.next().await {\n    Some(Err(e)) if is_unrecognized_sse_event(&e) => {\n        // Schema drift: abort the turn and surface for upgrade, do not retry\n        return Err(e.context(\"client out of date for Anthropic SSE protocol\"));\n    }\n    other => { /* forward */ }\n}","preventionTips":["Keep the client version current relative to Anthropic API changes","Treat unrecognized-event errors as version drift, not transient faults — never blind-retry","Capture the payload embedded in the serde error for a targeted mapping fix"],"tags":["anthropic","sse","schema","deserialization","version-drift"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}