Hmbown/CodeWhale · error

unrecognized SSE event: {e}

Error message

unrecognized SSE event: {e}

What it means

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.

Source

Thrown at crates/tui/src/client/anthropic.rs:817

        Some(known)
            if !matches!(
                known,
                "message_start"
                    | "content_block_start"
                    | "content_block_delta"
                    | "content_block_stop"
                    | "message_delta"
                    | "message_stop"
                    | "ping"
                    | "error"
            ) =>
        {
            return None;
        }
        _ => {}
    }

    Some(serde_json::from_value(value).map_err(|e| anyhow::anyhow!("unrecognized SSE event: {e}")))
}

/// Map Anthropic's usage payload onto the normalized [`Usage`] convention
/// (#2961 / #4318): hit = cache reads, write = cache creation, miss = raw
/// uncached input, `input_tokens` = the total prompt across all three.
fn parse_anthropic_usage(usage: &Value) -> Usage {
    let field = |name: &str| {
        usage
            .get(name)
            .and_then(Value::as_u64)
            .and_then(|value| u32::try_from(value).ok())
            .unwrap_or(0)
    };
    let input_raw = field("input_tokens");
    let cache_creation = field("cache_creation_input_tokens");
    let cache_read = field("cache_read_input_tokens");
    let output = field("output_tokens");

View on GitHub (pinned to 8880682c63)

Solutions

  1. Update the crate/TUI to the latest version — new event mappings are added as Anthropic ships them
  2. Check the Anthropic changelog for new streaming event types matching the serde error text
  3. Capture the failing payload and, for a local build, add a match arm returning `None` for the ignorable new type or a proper mapping
  4. Retry on the updated build; do not retry unchanged — the same event will fail again
Defensive patterns

Strategy: try-catch

Type guard

fn is_unrecognized_sse_event(err: &anyhow::Error) -> bool {
    err.to_string().starts_with("unrecognized SSE event")
}

Try / catch

match stream.next().await {
    Some(Err(e)) if is_unrecognized_sse_event(&e) => {
        // Schema drift: abort the turn and surface for upgrade, do not retry
        return Err(e.context("client out of date for Anthropic SSE protocol"));
    }
    other => { /* forward */ }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/43cfe1613822b449. Report an issue: GitHub.