Hmbown/CodeWhale · error
Reviewed plugin MCP authentication failed (provider details…
Error message
Reviewed plugin MCP authentication failed (provider details suppressed)
What it means
When building resolved HTTP headers for a reviewed plugin's MCP server, OAuth-based authentication failed. Because the server came from a reviewed plugin, `suppress_server_error_details` is set, so the library replaces the underlying OAuth error with this generic message to avoid leaking provider or endpoint details to the user.
Solutions
- Re-run the plugin connection with full error details enabled (suppress_server_error_details = false) to see the real OAuth failure
- Re-authenticate / clear cached OAuth tokens so a fresh token flow starts
- Verify network reachability of the MCP server's OAuth issuer/token endpoint
- Check the plugin's OAuth client configuration (client id, scopes, issuer URL)
Example fix
// before
let headers = transport.auth.resolved_headers().await?; // opaque suppressed error
// after
match transport.auth.resolved_headers().await {
Ok(h) => h,
Err(e) if e.to_string().contains("authentication failed") => {
// retry with details unsuppressed / re-auth flow
eprintln!("OAuth for reviewed plugin needs re-auth; rerun with diagnostics enabled");
return Err(e);
}
Err(e) => return Err(e),
} Defensive patterns
Strategy: retry
Validate before calling
// Before connecting, sanity-check OAuth inputs for the reviewed plugin
if oauth_issuer_unreachable(&plugin.oauth).await {
eprintln!("token endpoint unreachable; fix network or plugin OAuth config first");
} Try / catch
match transport.auth.resolved_headers().await {
Ok(h) => h,
Err(e) if e.to_string().contains("provider details suppressed") => {
// Re-authenticate, then retry once with details unsuppressed for diagnosis
refresh_oauth_tokens(&mut transport.oauth).await?;
transport.suppress_server_error_details = false;
transport.auth.resolved_headers().await?
}
Err(e) => return Err(e),
} Prevention
- Refresh OAuth tokens proactively before expiry
- Verify reviewed plugins' issuer/token endpoints are reachable in your environment
- Temporarily disable error-detail suppression when diagnosing auth failures
When it happens
Trigger: `resolved_headers` (crates/tui/src/mcp/http.rs:115) finds no static Authorization header and calls `oauth.authorization_header()`, which errors (expired/invalid token, unreachable token endpoint, missing client credentials) while server error details are suppressed.
Common situations: An OAuth access token expired and refresh failed; the token endpoint is unreachable (offline, firewall, DNS); the reviewed plugin's OAuth client credentials are wrong or revoked; clock skew invalidating token expiry.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- MCP server rejected the request with and refreshing the…
- MCP server rejected the request with ; the session is no…
- OAuth HTTP response body exceeds
- {}
- invalid MCP OAuth callback port 0
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/17591007b8a8cbd5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/mcp/http.rs:115
if !mcp_headers_have_authorization(&headers)
&& let Some(env_var) = self.bearer_token_env_var.as_deref()
&& let Ok(token) = self.reviewed_plugin.as_ref().map_or_else(
|| std::env::var(env_var),
|source| source.host_environment.var(env_var),
)
{
let token = token.trim();
if !token.is_empty() {
headers.insert("Authorization".to_string(), format!("Bearer {token}"));
}
}
if !mcp_headers_have_authorization(&headers)
&& let Some(oauth) = &self.oauth
{
let authorization = match oauth.authorization_header().await {
Ok(authorization) => authorization,
Err(_) if self.suppress_server_error_details => {
anyhow::bail!(
"Reviewed plugin MCP authentication failed (provider details suppressed)"
)
}
Err(error) => return Err(error),
};
if let Some(value) = authorization {
headers.insert("Authorization".to_string(), value);
}
}
Ok(headers)
}
}
pub(super) fn mcp_headers_have_authorization(headers: &HashMap<String, String>) -> bool {
headers
.keys()
.any(|key| key.trim().eq_ignore_ascii_case("authorization"))
}View on GitHub (pinned to 73e0f67d83)