BerriAI/litellm · error · HTTPException

This server requires PKCE: send code_challenge with code_cha

Error message

This server requires PKCE: send code_challenge with code_challenge_method=S256 on the authorization request

What it means

Raised by _require_s256_pkce when an authorization request against a PKCE-mandated server arrives without a code_challenge or with a method other than S256; the gateway refuses to start the flow because the server row requires proof-key exchange.

Source

Thrown at litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py:705

    upstream holds each client's own registration, so the authorize and token relays pass the
    client's ``client_id`` and ``redirect_uri`` through verbatim and the authorization code
    returns directly to the client's redirect URI without transiting the gateway. Gateway-side
    redirect trust and the ``/callback`` state relay therefore only apply to the short-circuit
    arm, where the upstream only knows the gateway's own callback."""
    return mcp_server.is_dcr_bridge and bool(mcp_server.registration_url) and not mcp_server.client_id


def _require_s256_pkce(
    code_challenge: str | None,
    code_challenge_method: str | None,
) -> tuple[str, str]:
    """DCR-bridge servers serve unauthenticated public OAuth clients, so the PKCE downgrade
    paths (no challenge, or a non-S256 method; RFC 7636 defaults a missing method to ``plain``)
    are rejected at the gateway instead of relying on upstream enforcement. Returns the
    validated pair so callers get non-optional values."""
    if code_challenge and code_challenge_method == "S256":
        return code_challenge, code_challenge_method
    raise HTTPException(
        status_code=400,
        detail=(
            "This server requires PKCE: send code_challenge with "
            "code_challenge_method=S256 on the authorization request"
        ),
    )


def _redirect_to_upstream_authorize(
    *,
    mcp_server: MCPServer,
    client_id: str,
    redirect_uri: str,
    state: str,
    code_challenge: str,
    code_challenge_method: str,
    response_type: str | None,
    scope: str | None,

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Include code_challenge with code_challenge_method=S256 on the authorization request.

Example fix

code_challenge=<s256>&code_challenge_method=S256
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at litellm/proxy/_experimental/mcp_server/discoverable_endpoints.py:705 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/7ee89715cab60ef1. Report an issue: GitHub.