Hmbown/CodeWhale · error · StreamableSendError::Other
MCP server rejected the request with ; the session is no…
Error message
MCP server {} rejected the request with {status}; the session is no longer accepted. {hint} What it means
After a failed OAuth refresh attempt (previous case) is exhausted, or when the auth path is exhausted, a rejected status on the MCP POST means the server no longer accepts the session. The client surfaces the masked server URL, the status, and a hint tailored to whether OAuth is configured, telling the developer the session must be re-established.
Solutions
- Re-authenticate / re-run the OAuth flow for the MCP server
- If OAuth is not configured but the server requires auth, configure OAuth credentials
- Retry the request so a fresh session id is negotiated
- Check server-side session/auth configuration and logs
Defensive patterns
Strategy: retry
Try / catch
match client.send(request).await {
Err(e) if e.to_string().contains("session is no longer accepted") => {
// start a fresh session (drop stale session id) and retry once
client.reset_session();
client.send(request).await
}
other => other,
} Prevention
- Re-negotiate the session id after any server restart or 4xx session rejection
- Configure OAuth when the server requires authentication
- Don't cache session ids across long idle periods
When it happens
Trigger: send() receives an auth-rejection status (e.g. 401/403) from the MCP server's POST response after the refresh-and-retry path did not apply or completed, and unauthorized_session_hint() builds guidance based on whether OAuth is configured.
Common situations: Server restarted and invalidated the session id; session revoked server-side; tokens expired and no OAuth configured; stale session id replayed after server state loss.
Related errors
- MCP server rejected the request with and refreshing the…
- MCP session expired
- MCP Streamable HTTP session expired; retry with a new…
- Reviewed plugin MCP authentication failed (provider details…
- MCP HTTP destination blocked by network policy
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/8b3ce135fa508daf.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp/streamable_http.rs:128
if status == StatusCode::UNAUTHORIZED || status == StatusCode::FORBIDDEN {
if !retried && let Some(oauth) = self.auth.oauth.as_ref() {
match oauth.force_refresh().await {
Ok(()) => {
retried = true;
continue;
}
Err(refresh_error) => {
return Err(StreamableSendError::Other(anyhow::anyhow!(
"MCP server {} rejected the request with {status} and refreshing the OAuth session failed: {refresh_error:#}. {hint}",
mask_url_secrets(&self.url),
hint = oauth_refresh_failed_hint(),
)));
}
}
}
let hint = unauthorized_session_hint(self.auth.oauth_configured);
return Err(StreamableSendError::Other(anyhow::anyhow!(
"MCP server {} rejected the request with {status}; the session is no longer accepted. {hint}",
mask_url_secrets(&self.url),
)));
}
if !status.is_success() {
let body_excerpt = bounded_body_excerpt(response, ERROR_BODY_PREVIEW_BYTES).await;
let stale_session = self.session_id.is_some()
&& is_streamable_http_stale_session_status(status, &body_excerpt);
let body_excerpt = self.auth.server_error_preview(&body_excerpt);
if stale_session {
return Err(StreamableSendError::StaleSession(format!(
"status={status} body={body_excerpt}"
)));
}
if is_streamable_http_incompatible_status(status) {
return Err(StreamableSendError::Incompatible(format!(
"status={status} body={body_excerpt}"View on GitHub (pinned to 73e0f67d83)