Hmbown/CodeWhale · error · anyhow
OAuth HTTP response body exceeds
Error message
OAuth HTTP response body exceeds {MAX_OAUTH_HTTP_RESPONSE_BODY_BYTES} bytes What it means
The OAuth HTTP client enforces a hard cap (MAX_OAUTH_HTTP_RESPONSE_BODY_BYTES) on how many bytes it will read from an OAuth endpoint's response body. While streaming the body chunk-by-chunk, if the next chunk would push the accumulated body past the limit, the read is aborted and this error is returned. This protects the client from memory exhaustion caused by a malicious or misbehaving OAuth server returning an oversized response.
Solutions
- Verify the OAuth issuer/discovery URL points at the real OAuth server, not a proxy or login page returning large HTML
- Inspect what the server actually returns (curl the URL) and fix the server-side response
- If the limit is genuinely too small for a legitimate deployment, raise MAX_OAUTH_HTTP_RESPONSE_BODY_BYTES deliberately
Example fix
// before: metadata URL behind a captive portal returning an HTML page "discovery_url": "https://portal.example.com/.well-known/oauth-authorization-server" // after: point directly at the real issuer "discovery_url": "https://auth.example.com/.well-known/oauth-authorization-server"
Defensive patterns
Strategy: validation
Validate before calling
let url = discovery_url;
if !url.starts_with("https://") || url.contains("portal") {
// verify the endpoint actually returns a small JSON document before use
}
// optionally: HEAD/GET the URL and check Content-Length < MAX_OAUTH_HTTP_RESPONSE_BODY_BYTES Try / catch
match oauth_exchange_result {
Err(e) if e.to_string().contains("exceeds") => {
// treat as untrusted/misbehaving OAuth endpoint; refuse to proceed and log
}
other => other?,
} Prevention
- Point discovery/token URLs directly at the real OAuth issuer, never at a portal or proxy page
- Curl each configured OAuth URL once during setup and confirm it returns small JSON
- Never disable or blindly raise the body cap to work around a bad endpoint
When it happens
Trigger: Any OAuth HTTP exchange (token request, discovery, JWKS fetch, etc.) where the server's response body length exceeds MAX_OAUTH_HTTP_RESPONSE_BODY_BYTES; detected inside the response.chunk() streaming loop after the accumulated body plus the next chunk exceeds the limit.
Common situations: Pointing the OAuth discovery/authorization metadata URL at a misconfigured proxy or portal that returns a large HTML error/login page instead of a small JSON document; a compromised or rogue MCP server deliberately flooding the response; a reverse proxy returning a huge interstitial page.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- MCP response Content-Length
- MCP server rejected the request with and refreshing the…
- Reviewed plugin MCP authentication failed (provider details…
- invalid MCP OAuth callback port 0
- MCP HTTP destination blocked by network policy
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/14fb4e60d96db8e0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp/oauth.rs:322
let mut response = self
.client
.execute(
request,
matches!(redirect_policy, OAuthHttpRedirectPolicy::Follow),
)
.await
.map_err(|error| -> OAuthHttpClientError { error.into() })?;
let status = response.status();
let version = response.version();
let headers = response.headers().clone();
let mut body = Vec::new();
while let Some(chunk) = response
.chunk()
.await
.map_err(|error| Box::new(error) as OAuthHttpClientError)?
{
if chunk.len() > MAX_OAUTH_HTTP_RESPONSE_BODY_BYTES - body.len() {
return Err(anyhow!(
"OAuth HTTP response body exceeds {MAX_OAUTH_HTTP_RESPONSE_BODY_BYTES} bytes"
)
.into());
}
body.extend_from_slice(&chunk);
}
if is_token_request {
*self
.last_token_response
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner) =
Some(TokenEndpointReceipt::from_response(status, &headers, &body));
}
let mut builder = oauth2::http::Response::builder()
.status(status)
.version(version);
for (name, value) in &headers {
builder = builder.header(name, value);View on GitHub (pinned to 73e0f67d83)