PrefectHQ/fastmcp · error · RuntimeError
Authorization failed: {response.status_code}
Error message
Authorization failed: {response.status_code} What it means
callback_handler expects the stored redirect response to be a 3xx redirect carrying the authorization code. If the response has any other status code, it raises RuntimeError with the actual status, meaning the authorization request did not produce a redirect (e.g. the provider rendered an error page).
Source
Thrown at fastmcp_slim/fastmcp/utilities/tests.py:514
# keep_blank_values=True so explicitly-empty params (e.g. ?state=)
# survive parsing instead of being silently dropped. Real OAuth
# callbacks can include empty `state` or `error_description`,
# and downstream code distinguishes "" from missing.
query_params = parse_qs(parsed.query, keep_blank_values=True)
if "error" in query_params:
error = query_params["error"][0]
error_desc = query_params.get("error_description", ["Unknown error"])[0]
raise RuntimeError(
f"OAuth authorization failed: {error} - {error_desc}"
)
auth_code = query_params["code"][0]
state = query_params.get("state", [None])[0]
iss = query_params.get("iss", [None])[0]
return AuthorizationCodeResult(code=auth_code, state=state, iss=iss)
else:
raise RuntimeError(f"Authorization failed: {response.status_code}")
View on GitHub (pinned to 1f02114297)
Solutions
- Check response.status_code in the message and fetch the response body/HTML to see the provider's error page
- Verify the authorization endpoint URL and query parameters (client_id, redirect_uri, scope, PKCE challenge)
- In tests, pre-authenticate the HTTP client/cookie jar so the provider does not return a login page
- Retry if the status is 5xx — the provider may be temporarily unavailable
Defensive patterns
Strategy: try-catch
Validate before calling
assert 300 <= response.status_code < 400, f"expected redirect, got {response.status_code}" Try / catch
try:
result = await helper.callback_handler()
except RuntimeError as e:
if "Authorization failed" in str(e):
status = int(str(e).rsplit(":", 1)[1])
if status >= 500: retry_authorization()
raise Prevention
- Pre-authenticate the client so the provider returns a redirect, not a login page
- Validate authorization URL parameters before the request
- Treat 5xx statuses as transient and retry
- Log the response body to see the provider error page
When it happens
Trigger: follow_redirects=False GET to the authorization URL returns 200 (login/error page), 4xx (bad request, invalid client), or 5xx (provider outage) instead of a redirect; callback_handler then hits the else branch and raises.
Common situations: Wrong authorization endpoint URL; provider requiring login so the response is an HTML sign-in page; network/proxy issues in CI returning 502/503; provider returning 400 due to malformed PKCE/state parameters.
Related errors
- No authorization response stored. redirect_handler must be c
- OAuth authorization failed: {error} - {error_desc}
- OAuth client not found - cached credentials may be stale
- Unexpected authorization response: {response.status_code}
- OAuth server rejected the static client credentials. Verify
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/0a55dd509d9046a4.
Report an issue: GitHub.