BerriAI/litellm · error · Exception

Invalid proxy server token passed. valid_token=None.

Error message

Invalid proxy server token passed. valid_token=None.

What it means

Raised in _is_api_route_allowed when the route-authorization step runs with valid_token=None, i.e. user_api_key_auth could not resolve the presented bearer token to any virtual key or master key. It indicates the request reached the allowed-routes check with no authenticated identity at all.

Source

Thrown at litellm/proxy/auth/auth_checks.py:999

        return LitellmUserRoles.INTERNAL_USER

    return role


def _is_api_route_allowed(
    route: str,
    request: Request,
    request_data: dict,
    valid_token: UserAPIKeyAuth | None,
    user_obj: LiteLLM_UserTable | None = None,
) -> bool:
    """
    - Route b/w api token check and normal token check
    """
    _user_role: Final = _get_user_role(user_obj=user_obj)

    if valid_token is None:
        raise Exception("Invalid proxy server token passed. valid_token=None.")

    if not _is_user_proxy_admin(user_obj=user_obj):  # if non-admin
        RouteChecks.non_proxy_admin_allowed_routes_check(
            user_obj=user_obj,
            _user_role=_user_role,
            route=route,
            request=request,
            request_data=request_data,
            valid_token=valid_token,
        )
    return True


def _is_user_proxy_admin(user_obj: LiteLLM_UserTable | None):
    if user_obj is None:
        return False

    if user_obj.user_role is not None and user_obj.user_role == LitellmUserRoles.PROXY_ADMIN.value:

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Verify the key exists and is active: GET /key/info?key=sk-... with an admin key
  2. Regenerate the key and redeploy it to clients, checking for trailing whitespace/newlines
  3. Confirm the proxy has a database connected (virtual keys are DB-backed)
  4. Check the Authorization header format is exactly 'Bearer <key>'

Example fix

# before
API_KEY="sk-abc123\n"  # stray newline from env file

# after
API_KEY=$(echo -n "$API_KEY" | tr -d '\n')
# or fix the .env / secret so no newline is stored
Defensive patterns

Strategy: try-catch

Validate before calling

# preflight: confirm the key resolves before real traffic (admin key required)
def key_is_valid(proxy_url: str, admin_key: str, key: str) -> bool:
    resp = requests.get(
        f"{proxy_url}/key/info",
        params={"key": key.strip()},
        headers={"Authorization": f"Bearer {admin_key}"},
    )
    return resp.status_code == 200

Try / catch

try:
    resp = client.chat.completions.create(model="gpt-4o", messages=messages)
except Exception as e:
    if "Invalid proxy server token" in str(e) or "valid_token=None" in str(e):
        raise PermissionError("key not recognized by proxy - check/rotate it") from e
    raise

Prevention

When it happens

Trigger: Calling a proxy route with an unknown, deleted, or malformed key in the Authorization header; keys whose lookup returns None (DB absent so key rows cannot load, rotated key still in use, key value with trailing whitespace/newline from env expansion).

Common situations: Key rotated or revoked but clients still hold the old value; DATABASE_URL missing so virtual keys cannot be resolved; copied key with a stray newline from a .env file or k8s secret; hitting the wrong port with an upstream provider key.

Related errors


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