BerriAI/litellm · error · Exception

Tried to access route={route}, which is only for MASTER KEY

Error message

Tried to access route={route}, which is only for MASTER KEY

What it means

Some proxy routes are reserved for the master key alone (listed in `LiteLLMRoutes.master_key_only_routes`). When the presented key is NOT the master key and the requested route is on that list, auth aborts with this exception before any handler logic runs — regardless of the caller's other permissions.

Source

Thrown at litellm/proxy/auth/user_api_key_auth.py:1707

                _cache_key_object(
                    hashed_token=hash_token(master_key),
                    user_api_key_obj=_user_api_key_obj,
                    user_api_key_cache=user_api_key_cache,
                    proxy_logging_obj=proxy_logging_obj,
                )
            )

            _user_api_key_obj = update_valid_token_with_end_user_params(
                valid_token=_user_api_key_obj, end_user_params=end_user_params
            )
            _user_api_key_obj.via_virtual_key = True

            return _user_api_key_obj

        ## IF it's not a master key
        ## Route should not be in master_key_only_routes
        if route in LiteLLMRoutes.master_key_only_routes.value:
            raise Exception(f"Tried to access route={route}, which is only for MASTER KEY")

        ## Check DB

        if (
            prisma_client is None
        ):  # if both master key + user key submitted, and user key != master key, and no db connected, raise an error
            raise ProxyException(
                message="No connected db.",
                type=ProxyErrorTypes.no_db_connection,
                code=400,
                param=None,
            )

        if valid_token is None:
            if isinstance(api_key, str):  # if generated token, make sure it starts with sk-.
                _masked_key: Final = f"{api_key[:4]}****{api_key[-4:]}" if len(api_key) > 8 else "****"
                if not api_key.startswith("sk-"):
                    _hint = _JWT_AUTH_DISABLED_HINT if not enable_jwt_auth and JWTHandler.is_jwt(token=api_key) else ""

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Authenticate that request with the master key (`Authorization: Bearer <LITELLM_MASTER_KEY>`)
  2. If the restriction is unwanted, edit `general_settings.master_key_only_routes` in config to remove the route (accepting the security tradeoff)
  3. Split workflows: service accounts use virtual keys for inference, a secrets-managed master key for admin operations

Example fix

# before
client = OpenAI(base_url=..., api_key=user_virtual_key)
client.post("/key/generate", json={...})  # -> only for MASTER KEY

# after (dedicated admin client from secret store)
admin = OpenAI(base_url=..., api_key=os.environ["LITELLM_MASTER_KEY"])
admin.post("/key/generate", json={...})
Defensive patterns

Strategy: validation

Validate before calling

MASTER_KEY_ONLY = {"/key/generate", "/key/delete", "/global/spend/report"}  # mirror your config list
key = MASTER_KEY if route in MASTER_KEY_ONLY else service_key
headers = {"Authorization": f"Bearer {key}"}

Try / catch

try:
    r = httpx.post(f"{PROXY}{route}", headers=headers)
except Exception as e:
    if "only for MASTER KEY" in str(e):
        raise PermissionError(f"{route} requires the master key; rerun with elevated credential") from e
    raise

Prevention

When it happens

Trigger: Calling an admin-only route such as key/team/global management endpoints with a virtual key or team key instead of `LITELLM_MASTER_KEY`; e.g. `POST /key/generate` or router-level admin routes with a normal user's `sk-` key.

Common situations: Automation scripts provisioned with a virtual key that later need master-only operations; org admin assuming their admin role key suffices (role != master key); a config adding routes to `master_key_only_routes` that a service account's workflow depends on.

Related errors


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