langchain-ai/deepagents · error · RuntimeError

Device flow failed: {err}: {body.get('error_description', ''

Error message

Device flow failed: {err}: {body.get('error_description', '')}

What it means

This RuntimeError is raised by `_run_device_flow` in mcp_auth.py when the GitHub OAuth device-flow token poll returns a terminal `error` value in its response body. Only transient errors (`authorization_pending`, `slow_down`) are retried; any other error (e.g. `access_denied`, `expired_token`) aborts the flow with the error code and GitHub's `error_description` embedded in the message.

Source

Thrown at libs/code/deepagents_code/mcp_auth.py:1963

            except ValueError as exc:
                # Malformed JSON would otherwise cascade into a confusing
                # OAuthToken.model_validate({}) error below; log the cause
                # explicitly so debugging is possible.
                logger.warning(
                    "Token endpoint %s returned non-JSON body: %s",
                    token_url,
                    exc,
                )
                body = {}
            err = body.get("error")
            if err == "authorization_pending":
                continue
            if err == "slow_down":
                interval += 5
                continue
            if err:
                msg = f"Device flow failed: {err}: {body.get('error_description', '')}"
                raise RuntimeError(msg)
            try:
                token_response.raise_for_status()
            except httpx.HTTPStatusError as exc:
                msg = (
                    f"Token request failed: HTTP {token_response.status_code} "
                    f"from {token_url}."
                )
                raise RuntimeError(msg) from exc
            try:
                return OAuthToken.model_validate(body)
            except ValidationError as exc:
                msg = (
                    f"Token response from {token_url} is not a valid "
                    f"OAuth token payload: {exc}"
                )
                raise RuntimeError(msg) from exc

    msg = "Device flow timed out. Try logging in again."

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Re-run the login command and complete the authorization in the browser promptly before the device code expires
  2. Check the `error_description` in the message — if `access_denied`, the user declined; approve the request on the github.com/activate page
  3. Verify network/proxy settings allow HTTPS POSTs to github.com's OAuth token endpoint
  4. If `expired_token` recurs, retry login immediately after starting the flow rather than delaying confirmation

Example fix

// before: delaying too long before confirming
code = start_login()
time.sleep(900)  # device code expires
run_cli_login()
// after
run_cli_login()  # confirm the code in the browser immediately
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-call validation possible; errors come from the interactive poll.
// Ensure network access to github.com and complete browser auth promptly.

Try / catch

try:
    login(server_name)
except RuntimeError as exc:
    if "Device flow failed" in str(exc):
        print(f"GitHub denied the device flow: {exc}. Re-run login and approve the request.")
    raise

Prevention

When it happens

Trigger: Calling `login` (via `_preseed_github_auth`) for an http/sse MCP server while the device-flow poll endpoint returns a non-retryable error field: the user denied the authorization request, the device code expired before confirmation, or the poll request was otherwise rejected.

Common situations: User clicks 'Cancel' on the GitHub activation page; user takes too long to enter the code so it expires; corporate proxy or SSO policy blocks the token endpoint; clock/network issues cause the polling loop to outlive the code's lifetime.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/795316bb50df2182. Report an issue: GitHub.