{"record":{"id":"2af8b50ea45a57a8","repo":"Hmbown/CodeWhale","slug":"sse-transport-cancelled-before-endpoint-was-discov","errorCode":null,"errorMessage":"SSE transport cancelled before endpoint was discovered","messagePattern":"SSE transport cancelled before endpoint was discovered","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/tui/src/mcp/sse.rs","lineNumber":215,"sourceCode":"                        return Ok(());\n                    }\n                }\n            }\n        }\n        Ok(())\n    }\n\n    async fn wait_for_endpoint(\n        &mut self,\n        cancel_token: &tokio_util::sync::CancellationToken,\n        endpoint_timeout: Duration,\n    ) -> Result<()> {\n        let timeout = tokio::time::sleep(endpoint_timeout);\n        tokio::pin!(timeout);\n\n        let msg = tokio::select! {\n            _ = cancel_token.cancelled() => {\n                anyhow::bail!(\"SSE transport cancelled before endpoint was discovered\");\n            }\n            _ = &mut timeout => {\n                anyhow::bail!(\n                    \"SSE endpoint not received within {}ms\",\n                    endpoint_timeout.as_millis()\n                );\n            }\n            msg = self.receiver.recv() => {\n                msg.context(\"SSE transport closed before endpoint was discovered\")?\n            }\n        };\n\n        match msg {\n            SseInbound::Endpoint(endpoint) => self.store_endpoint(&endpoint),\n            SseInbound::Message(_) => {\n                anyhow::bail!(\"MCP SSE server sent a message before declaring its endpoint\");\n            }\n        }","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/mcp/sse.rs#L197-L233","documentation":"`wait_for_endpoint` blocks until the SSE server declares its message endpoint. If the cancellation token fires while waiting, the wait is aborted with this error (this branch takes priority over the timeout and channel receive in the select).","triggerScenarios":"Cancelling the token after the SSE stream connected but before the server sent its `endpoint` event.","commonSituations":"Shutdown or user abort mid-handshake; supervisor tearing down a hung server that never sent the endpoint event.","solutions":["If unexpected, find what cancels the token during startup and defer it until after handshake","Treat as benign teardown: catch and exit without retrying","If the server is slow to send the endpoint event, fix the server or raise the endpoint timeout"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match wait_for_endpoint(...).await {\n    Err(e) if e.to_string().contains(\"cancelled before endpoint\") => info!(\"aborted during handshake\"),\n    other => other?,\n}","preventionTips":["Keep cancellation tokens alive through the full handshake; cancel only on real teardown"],"tags":["mcp","sse","cancellation"],"backgroundTag":"operation-cancelled","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}