PrefectHQ/fastmcp · error · RuntimeError
Unexpected authorization response: {response.status_code}
Error message
Unexpected authorization response: {response.status_code} What it means
After the pre-flight GET of the authorization URL, FastMCP only accepts 200 (HTML login page) or redirect statuses (302/303/307/308). Any other status — 401, 403, 500, 502, etc. — means the authorization endpoint answered in a way the OAuth flow cannot proceed with, so redirect_handler raises RuntimeError before opening the browser.
Source
Thrown at fastmcp_slim/fastmcp/client/auth/oauth.py:395
"OAuth dynamic registration returned an expired client secret"
)
return await super()._perform_authorization()
async def redirect_handler(self, authorization_url: str) -> None:
"""Open browser for authorization, with pre-flight check for invalid client."""
# Pre-flight check to detect invalid client_id before opening browser
async with self.httpx_client_factory() as client:
response = await client.get(authorization_url, follow_redirects=False)
# Check for client not found error (400 typically means bad client_id)
if response.status_code == 400:
raise ClientNotFoundError(
"OAuth client not found - cached credentials may be stale"
)
# OAuth typically returns redirects, but some providers return 200 with HTML login pages
if response.status_code not in (200, 302, 303, 307, 308):
raise RuntimeError(
f"Unexpected authorization response: {response.status_code}"
)
logger.info(f"OAuth authorization URL: {authorization_url}")
webbrowser.open(authorization_url)
async def callback_handler(self) -> AuthorizationCodeResult:
"""Handle OAuth callback and return the authorization code result."""
# Create result container and event to capture the OAuth response
result = OAuthCallbackResult()
result_ready = anyio.Event()
# Create server with result tracking
server: Server = create_oauth_callback_server(
port=self.redirect_port,
host=self._callback_host,
server_url=self.mcp_url,
result_container=result,View on GitHub (pinned to 1f02114297)
Solutions
- Check the logged authorization URL and hit it in a browser to see the actual response/error page.
- Verify the server's authorization server metadata (issuer URL) resolves to the correct authorize endpoint.
- Check for proxies/WAFs intercepting the request and allowlist the endpoint.
- Retry later if the provider is returning 5xx (outage).
Example fix
// before: issuer typo yields 404 from authorize endpoint OAuth(mcp_url='https://mcp.example.com/mcp', api_base_url='https://auth.example.com') // after: correct issuer so discovery returns a valid authorize endpoint OAuth(mcp_url='https://mcp.example.com/mcp', api_base_url='https://auth.correct-tenant.example.com')
Defensive patterns
Strategy: fallback
Validate before calling
import httpx
resp = httpx.get(authorization_url, follow_redirects=False)
if resp.status_code not in (200, 302, 303, 307, 308):
print(resp.status_code, resp.headers.get('location'), resp.text[:200]) Try / catch
try:
async with client:
await client.list_tools()
except RuntimeError as e:
if 'Unexpected authorization response' in str(e):
log_authorization_url_and_retry_later() # provider outage / wrong endpoint
raise Prevention
- Verify the issuer/discovery metadata URL is correct before wiring up OAuth.
- Manually open the authorization URL in a browser once to confirm the endpoint responds.
- Check proxy/WAF rules for the authorize endpoint in corporate networks.
- Monitor the identity provider's status for 5xx outages.
When it happens
Trigger: redirect_handler receives a status code outside (200, 302, 303, 307, 308): e.g. the authorization server returns 401/403 (auth required on the authorize endpoint itself), 404 (wrong issuer/authorize path in discovery metadata), or 5xx (provider outage or proxy error).
Common situations: Misconfigured OIDC discovery metadata pointing at the wrong authorization endpoint; corporate proxy or WAF returning 403/502; identity provider down or returning 500; server behind auth gateway that rejects the pre-flight GET.
Related errors
- str(e)
- {str(e) from SSRFError/SSRFFetchError}
- OIDC discovery for issuer {issuer!r} failed: {e}
- OAuth token endpoint error: {token['error']}: {token.get('er
- HTTP {response.status_code} fetching {url}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/21343fd4a31b0c9d.
Report an issue: GitHub.