BerriAI/litellm · error · HTTPException

Virtual key is not allowed to call this route. Only allowed

Error message

Virtual key is not allowed to call this route. Only allowed to call routes: {valid_token.allowed_routes}. Tried to call route: {route}

What it means

Raised in RouteChecks when a virtual key carries an allowed_routes restriction and the incoming request's route is not in that list (after the documented carve-outs, e.g. read-only MCP discovery GETs, are applied). Both the key's allowed routes and the attempted route are embedded; the fix is on the proxy-admin side — extend allowed_routes for that key.

Source

Thrown at litellm/proxy/auth/route_checks.py:176

                        # so virtual keys with allowed_routes=["llm_api_routes"]
                        # can list/inspect MCP servers. The GET handlers in
                        # mcp_management_endpoints.py sanitize the response
                        # for restricted virtual keys (stripping url,
                        # headers, env, credentials). POST/PUT/DELETE on
                        # these paths are admin-only management writes and
                        # are intentionally not covered.
                        if RouteChecks._is_get_mcp_server_discovery_route(route=route, request=request):
                            return True

        # check if wildcard pattern is allowed
        for allowed_route in valid_token.allowed_routes:
            if RouteChecks._route_matches_wildcard_pattern(route=route, pattern=allowed_route):
                return True

        if denied_auth_enforced_pass_through_route:
            raise RouteChecks._auth_pass_through_denied_exception(route=route)

        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail=f"Virtual key is not allowed to call this route. Only allowed to call routes: {valid_token.allowed_routes}. Tried to call route: {route}",
        )

    @staticmethod
    def _mask_user_id(user_id: str) -> str:
        """
        Mask user_id to prevent leaking sensitive information in error messages

        Args:
            user_id (str): The user_id to mask

        Returns:
            str: Masked user_id showing only first 2 and last 2 characters
        """
        from litellm.litellm_core_utils.sensitive_data_masker import SensitiveDataMasker

        if not user_id or len(user_id) <= 4:

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Call one of the routes listed in the key's allowed_routes.
  2. Update the key via /key/update to include the route you need.

Example fix

curl -X POST $PROXY/key/update -d '{"key": "sk-...", "allowed_routes": ["/chat/completions"]}'
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at litellm/proxy/auth/route_checks.py:176 when the library encounters an invalid state.

Common situations: The virtual key's allowed_routes does not include the requested route.


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