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
- Increase the endpoint timeout to tolerate slow servers
- Verify the server actually implements the SSE transport and sends an endpoint event on connect
- Check intermediaries (proxy, auth layer) for buffering that withholds the first event
- 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
- Set the endpoint timeout generously (seconds, not milliseconds)
- Verify servers implement the SSE endpoint announcement
- Watch for proxies buffering the first event
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
- MCP SSE frame exceeded
- MCP SSE server sent a message before declaring its endpoint
- {err}
- JSON-RPC line exceeded the
- MCP exceeded its overall deadline
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)