Hmbown/CodeWhale · error

SSE endpoint not received within

Error message

SSE endpoint not received within {}ms

What it means

After connecting, the SSE protocol requires the server to announce its message endpoint within `endpoint_timeout`. If no endpoint event arrives in time, the client gives up with this error naming the timeout in milliseconds.

Solutions

  1. Increase the endpoint timeout to tolerate slow servers
  2. Verify the server actually implements the SSE transport and sends an endpoint event on connect
  3. Check intermediaries (proxy, auth layer) for buffering that withholds the first event
  4. Retry the connection; a one-off stall may clear
Defensive patterns

Strategy: retry

Try / catch

for attempt in 0..3 {
    match wait_for_endpoint(...).await {
        Err(e) if e.to_string().contains("not received within") && attempt < 2 => continue,
        other => break other,
    }
}

Prevention

When it happens

Trigger: Server connects but never sends the `endpoint` event within the configured timeout — hung/broken server, wrong transport negotiation, or a very slow server with too small a timeout.

Common situations: Server that accepts the SSE connection but stalls; an intermediary eating the first event; extremely loaded server; timeout configured too aggressively (a few hundred ms).

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/mcp/sse.rs:218

            }
        }
        Ok(())
    }

    async fn wait_for_endpoint(
        &mut self,
        cancel_token: &tokio_util::sync::CancellationToken,
        endpoint_timeout: Duration,
    ) -> Result<()> {
        let timeout = tokio::time::sleep(endpoint_timeout);
        tokio::pin!(timeout);

        let msg = tokio::select! {
            _ = cancel_token.cancelled() => {
                anyhow::bail!("SSE transport cancelled before endpoint was discovered");
            }
            _ = &mut timeout => {
                anyhow::bail!(
                    "SSE endpoint not received within {}ms",
                    endpoint_timeout.as_millis()
                );
            }
            msg = self.receiver.recv() => {
                msg.context("SSE transport closed before endpoint was discovered")?
            }
        };

        match msg {
            SseInbound::Endpoint(endpoint) => self.store_endpoint(&endpoint),
            SseInbound::Message(_) => {
                anyhow::bail!("MCP SSE server sent a message before declaring its endpoint");
            }
        }
    }

    fn store_endpoint(&mut self, endpoint: &str) -> Result<()> {

View on GitHub (pinned to 73e0f67d83)