{"record":{"id":"0a55dd509d9046a4","repo":"PrefectHQ/fastmcp","slug":"authorization-failed-response-status-code","errorCode":null,"errorMessage":"Authorization failed: {response.status_code}","messagePattern":"Authorization failed: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/utilities/tests.py","lineNumber":514,"sourceCode":"            # keep_blank_values=True so explicitly-empty params (e.g. ?state=)\n            # survive parsing instead of being silently dropped. Real OAuth\n            # callbacks can include empty `state` or `error_description`,\n            # and downstream code distinguishes \"\" from missing.\n            query_params = parse_qs(parsed.query, keep_blank_values=True)\n\n            if \"error\" in query_params:\n                error = query_params[\"error\"][0]\n                error_desc = query_params.get(\"error_description\", [\"Unknown error\"])[0]\n                raise RuntimeError(\n                    f\"OAuth authorization failed: {error} - {error_desc}\"\n                )\n\n            auth_code = query_params[\"code\"][0]\n            state = query_params.get(\"state\", [None])[0]\n            iss = query_params.get(\"iss\", [None])[0]\n            return AuthorizationCodeResult(code=auth_code, state=state, iss=iss)\n        else:\n            raise RuntimeError(f\"Authorization failed: {response.status_code}\")\n","sourceCodeStart":496,"sourceCodeEnd":515,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/utilities/tests.py#L496-L515","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"assert 300 <= response.status_code < 400, f\"expected redirect, got {response.status_code}\"","typeGuard":null,"tryCatchPattern":"try:\n    result = await helper.callback_handler()\nexcept RuntimeError as e:\n    if \"Authorization failed\" in str(e):\n        status = int(str(e).rsplit(\":\", 1)[1])\n        if status >= 500: retry_authorization()\n    raise","preventionTips":["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"],"tags":["oauth","http","auth","testing"],"backgroundTag":"oauth-authorization-failed","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}