Hmbown/CodeWhale · error

Zen Responses stream event

Error message

Zen Responses stream event

What it means

Test-side `.expect("Zen Responses stream event")` panic. A single item yielded by the SSE stream was an `Err`, i.e. the request started but one streamed event failed to parse or the stream aborted mid-way. The mock only sends `data: [DONE]\n\n`, so the failure means the Responses SSE framing/terminator handling does not accept that payload.

Solutions

  1. Log the failing event's error (`event.expect(...)` -> print `{e:?}`) to see whether it is a parse error or a stream transport error.
  2. Verify the mock response keeps `Content-Type: text/event-stream` and the body ends with `data: [DONE]\n\n`.
  3. Check the SSE decoder treats `data: [DONE]` as stream termination, not an unknown event kind.
  4. If you changed the fixture body, make every emitted event valid per the Responses wire parser.

Example fix

// before
while let Some(event) = stream.next().await {
    event.expect("Zen Responses stream event");
}
// after (diagnosis)
while let Some(event) = stream.next().await {
    event.unwrap_or_else(|e| panic!("Zen Responses stream event: {e:?}"));
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust (validate the mock body is well-formed SSE before the client runs)
assert!(body.contains("data: [DONE]"), "fixture must terminate the SSE stream");

Try / catch

while let Some(event) = stream.next().await {
    if let Err(e) = event {
        panic!("stream event failed: {e:?}");
    }
}

Prevention

When it happens

Trigger: Running `opencode_zen_responses_request_uses_responses_route_without_oauth_headers` when the SSE parser rejects `data: [DONE]` (changed [DONE] semantics), emits an unexpected non-data line, or the server closes the stream in a way the event decoder treats as an error instead of a clean end.

Common situations: Upgrading the SSE/Responses event decoder; changing the mocked stream body to a multi-event fixture with a malformed event; Content-Type header dropped so the body is not parsed as an event stream.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/921952c88a692980. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/client.rs:8134

        Mock::given(method("POST"))
            .and(path("/v1/responses"))
            .respond_with(
                ResponseTemplate::new(200)
                    .insert_header("Content-Type", "text/event-stream")
                    .set_body_string("data: [DONE]\n\n"),
            )
            .expect(1)
            .mount(&server)
            .await;

        let client = opencode_zen_client(&server, "gpt-5.5");
        assert_eq!(client.wire_format, WireFormat::Responses);
        let mut stream = client
            .create_message_stream(minimal_zen_request("gpt-5.5"))
            .await
            .expect("Zen Responses request should start");
        while let Some(event) = stream.next().await {
            event.expect("Zen Responses stream event");
        }

        let requests = server.received_requests().await.expect("recorded request");
        assert_eq!(requests.len(), 1);
        assert_zen_bearer_without_codex_headers(&requests[0]);
        let body: Value = serde_json::from_slice(&requests[0].body).expect("Responses JSON body");
        assert_eq!(body.get("model").and_then(Value::as_str), Some("gpt-5.5"));
        assert!(body.get("input").is_some(), "Responses body: {body}");
        assert!(body.get("messages").is_none(), "Responses body: {body}");
    }

    #[tokio::test]
    async fn opencode_zen_messages_request_shape_uses_api_key_anthropic_route() {
        let server = MockServer::start().await;
        Mock::given(method("POST"))
            .and(path("/v1/messages"))
            .respond_with(ResponseTemplate::new(200).set_body_json(json!({
                "id": "msg_zen",

View on GitHub (pinned to 73e0f67d83)