BerriAI/litellm · error · XAIOAuthError

xAI OAuth state mismatch

Error message

xAI OAuth state mismatch

What it means

XAIOAuthError raised when the OAuth callback's returned state does not equal the state issued in the authorization URL — a classic CSRF/interception signal in the PKCE flow, so the callback result is rejected outright.

Source

Thrown at litellm/llms/xai/oauth.py:148

        verifier, challenge = self._pkce_pair()
        state: Final = uuid.uuid4().hex
        nonce: Final = uuid.uuid4().hex
        server, redirect_uri = self._start_callback_server(state)
        authorize_url: Final = self._build_authorize_url(
            authorization_endpoint=discovery["authorization_endpoint"],
            redirect_uri=redirect_uri,
            challenge=challenge,
            state=state,
            nonce=nonce,
        )

        if no_browser or not webbrowser.open(authorize_url):
            sys.stdout.write(f"Open this URL to authenticate with xAI:\n{authorize_url}\n")
            sys.stdout.flush()

        result: Final = self._wait_for_callback(server)
        if result.get("state") != state:
            raise XAIOAuthError("xAI OAuth state mismatch")
        if result.get("error"):
            description: Final = result.get("error_description") or result["error"]
            raise XAIOAuthError(f"xAI authorization failed: {description}")
        code: Final = result.get("code")
        if not code:
            raise XAIOAuthError("xAI authorization failed: no code returned")

        token_payload: Final = self._exchange_token(
            discovery["token_endpoint"],
            {
                "grant_type": "authorization_code",
                "code": code,
                "redirect_uri": redirect_uri,
                "client_id": XAI_OAUTH_CLIENT_ID,
                "code_verifier": verifier,
            },
        )
        auth_data: Final = self._build_auth_record(token_payload, discovery["token_endpoint"])

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Restart the OAuth login flow; a state mismatch means the callback does not match the original request (possible stale or tampered flow).
  2. Ensure you complete the login in the same session that started it and do not reuse old authorization URLs.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at litellm/llms/xai/oauth.py:148 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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