BerriAI/litellm · error · GetDeviceCodeError

Device code response missing fields

Error message

Device code response missing fields: {data}

What it means

GetDeviceCodeError (status 400) raised when the device-code endpoint answered HTTP 200 but the JSON body lacks device_auth_id or user_code (it does accept usercode as an alternate key). This is a response-shape mismatch: litellm parsed the JSON but could not find the fields the flow needs to display the verification code.

Solutions

  1. Upgrade litellm to the latest release so the parser matches the current OpenAI response schema
  2. Disable any proxy/mock that intercepts auth.openai.com and retry against the real endpoint
  3. Inspect the {data} payload echoed in the message to see what was actually returned
  4. If behind corporate middleware, allowlist the auth domain so responses pass through untouched
Defensive patterns

Strategy: try-catch

Try / catch

from litellm.llms.chatgpt.authenticator import GetDeviceCodeError

try:
    tokens = authenticator.login()
except GetDeviceCodeError as e:
    if "missing fields" in str(e):
        # response-shape mismatch: almost always fixed by a litellm upgrade
        print("Device-code response schema changed. Upgrade litellm: pip install -U litellm")
    raise

Prevention

When it happens

Trigger: A proxy or mock intercepting auth.openai.com and returning 200 with an unexpected body; OpenAI changing the device-code response schema in a way the installed litellm version does not understand.

Common situations: Running against a captured/replayed auth response in tests; a stale litellm version after OpenAI alters the OAuth contract; middleware (privacy proxies, captive portals) injecting a different 200 response.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/7c301813529fcc5c. Report an issue: GitHub.

Appendix: source

Thrown at litellm/llms/chatgpt/authenticator.py:189

            )
            resp.raise_for_status()
            data: Final = resp.json()
        except httpx.HTTPStatusError as exc:
            raise GetDeviceCodeError(
                message=f"Failed to request device code: {exc}",
                status_code=exc.response.status_code,
            )
        except Exception as exc:
            raise GetDeviceCodeError(
                message=f"Failed to request device code: {exc}",
                status_code=400,
            )

        device_auth_id: Final = data.get("device_auth_id")
        user_code: Final = data.get("user_code") or data.get("usercode")
        interval: Final = data.get("interval")
        if not device_auth_id or not user_code:
            raise GetDeviceCodeError(
                message=f"Device code response missing fields: {data}",
                status_code=400,
            )
        return {
            "device_auth_id": device_auth_id,
            "user_code": user_code,
            "interval": str(interval or "5"),
        }

    def _poll_for_authorization_code(self, device_code: dict[str, str]) -> dict[str, str]:
        client: Final = _get_httpx_client()
        interval: Final = int(device_code.get("interval", "5"))
        start_time: Final = time.time()
        while time.time() - start_time < DEVICE_CODE_TIMEOUT_SECONDS:
            try:
                resp = client.post(
                    CHATGPT_DEVICE_TOKEN_URL,
                    json={

View on GitHub (pinned to 77b7c6c40c)