{"record":{"id":"921952c88a692980","repo":"Hmbown/CodeWhale","slug":"zen-responses-stream-event","errorCode":null,"errorMessage":"Zen Responses stream event","messagePattern":"Zen Responses stream event","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/client.rs","lineNumber":8134,"sourceCode":"        Mock::given(method(\"POST\"))\n            .and(path(\"/v1/responses\"))\n            .respond_with(\n                ResponseTemplate::new(200)\n                    .insert_header(\"Content-Type\", \"text/event-stream\")\n                    .set_body_string(\"data: [DONE]\\n\\n\"),\n            )\n            .expect(1)\n            .mount(&server)\n            .await;\n\n        let client = opencode_zen_client(&server, \"gpt-5.5\");\n        assert_eq!(client.wire_format, WireFormat::Responses);\n        let mut stream = client\n            .create_message_stream(minimal_zen_request(\"gpt-5.5\"))\n            .await\n            .expect(\"Zen Responses request should start\");\n        while let Some(event) = stream.next().await {\n            event.expect(\"Zen Responses stream event\");\n        }\n\n        let requests = server.received_requests().await.expect(\"recorded request\");\n        assert_eq!(requests.len(), 1);\n        assert_zen_bearer_without_codex_headers(&requests[0]);\n        let body: Value = serde_json::from_slice(&requests[0].body).expect(\"Responses JSON body\");\n        assert_eq!(body.get(\"model\").and_then(Value::as_str), Some(\"gpt-5.5\"));\n        assert!(body.get(\"input\").is_some(), \"Responses body: {body}\");\n        assert!(body.get(\"messages\").is_none(), \"Responses body: {body}\");\n    }\n\n    #[tokio::test]\n    async fn opencode_zen_messages_request_shape_uses_api_key_anthropic_route() {\n        let server = MockServer::start().await;\n        Mock::given(method(\"POST\"))\n            .and(path(\"/v1/messages\"))\n            .respond_with(ResponseTemplate::new(200).set_body_json(json!({\n                \"id\": \"msg_zen\",","sourceCodeStart":8116,"sourceCodeEnd":8152,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/client.rs#L8116-L8152","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Log the failing event's error (`event.expect(...)` -> print `{e:?}`) to see whether it is a parse error or a stream transport error.","Verify the mock response keeps `Content-Type: text/event-stream` and the body ends with `data: [DONE]\\n\\n`.","Check the SSE decoder treats `data: [DONE]` as stream termination, not an unknown event kind.","If you changed the fixture body, make every emitted event valid per the Responses wire parser."],"exampleFix":"// before\nwhile let Some(event) = stream.next().await {\n    event.expect(\"Zen Responses stream event\");\n}\n// after (diagnosis)\nwhile let Some(event) = stream.next().await {\n    event.unwrap_or_else(|e| panic!(\"Zen Responses stream event: {e:?}\"));\n}","handlingStrategy":"try-catch","validationCode":"// Rust (validate the mock body is well-formed SSE before the client runs)\nassert!(body.contains(\"data: [DONE]\"), \"fixture must terminate the SSE stream\");","typeGuard":null,"tryCatchPattern":"while let Some(event) = stream.next().await {\n    if let Err(e) = event {\n        panic!(\"stream event failed: {e:?}\");\n    }\n}","preventionTips":["Always end mocked Responses streams with `data: [DONE]` and trailing blank line.","Keep `Content-Type: text/event-stream` on SSE fixtures.","Update the SSE decoder and its fixtures together when changing event shapes.","Log the raw SSE frame before parsing in failing tests."],"tags":["test-assertion","sse","streaming","rust"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}