PrefectHQ/fastmcp · error · DeviceAuthorizationError
Device authorization failed
Error message
Device authorization failed
What it means
The fallback branch of poll_device_authorization: any unrecognized error string from the token exchange (not authorization_pending, slow_down, access_denied, or expired_token) raises the generic DeviceAuthorizationError('Device authorization failed').
Source
Thrown at fastmcp_slim/fastmcp/cli/deploy/authentication.py:74
result = await client.exchange_device_authorization(authorization.device_code)
if result.access_token is not None:
return result.access_token
if result.error == "authorization_pending":
continue
if result.error == "slow_down":
interval += 5
continue
if result.error == "access_denied":
raise DeviceAuthorizationDeniedError(
"The device authorization request was denied"
)
if result.error == "expired_token":
raise DeviceAuthorizationExpiredError(
"The device authorization request expired"
)
raise DeviceAuthorizationError("Device authorization failed")
async def authorize_device(
client: HorizonClient,
*,
metadata: DeviceMetadata | None = None,
on_challenge: Callable[[DeviceAuthorization], None] | None = None,
open_browser: bool = False,
browser_opener: Callable[[str], object] = webbrowser.open,
sleep: Callable[[float], Awaitable[None]] | None = None,
monotonic: Callable[[], float] = time.monotonic,
) -> SecretStr:
"""Create, present, and complete a Horizon device authorization."""
authorization = await client.create_device_authorization(metadata)
if on_challenge is not None:
on_challenge(authorization)
if open_browser:View on GitHub (pinned to 1f02114297)
Solutions
- Log/print the raw error value returned by the token endpoint to identify the unknown code
- Upgrade fastmcp so poll_device_authorization understands newer device-flow error codes
- Check Horizon service status / network middleboxes that may alter error responses
- Retry the login flow with a fresh device authorization
Defensive patterns
Strategy: try-catch
Try / catch
from fastmcp.cli.deploy.authentication import DeviceAuthorizationError
try:
token = await poll_device_authorization(client, authorization)
except DeviceAuthorizationError as e:
logger.exception("Device authorization failed: %s", e)
token = await authorize_device(client, metadata=metadata) Prevention
- Keep fastmcp updated so new device-flow error codes are recognized
- Inspect raw token-endpoint responses when using a custom HorizonClient
- Retry the flow once before escalating; unknown errors are often transient
When it happens
Trigger: client.exchange_device_authorization returns a result whose error is an unexpected/unknown code (e.g. new server-side error types, 'invalid_grant', or malformed error responses).
Common situations: Horizon server version introducing a new OAuth error code; proxy/gateway returning non-standard error bodies; bugs in a custom HorizonClient stub used in tests.
Related errors
- The device authorization request expired
- The device authorization request was denied
- OAuth client not found - cached credentials may be stale
- Unexpected authorization response: {response.status_code}
- OAuth callback timed out after {self._callback_timeout} seco
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/a5593443faab898a.
Report an issue: GitHub.