BerriAI/litellm · error · Exception
User={valid_token.user_id} has been deactivated via SCIM. Ke
Error message
User={valid_token.user_id} has been deactivated via SCIM. Keys owned by this user cannot be used. What it means
SCIM offboarding enforcement: the token's owning user was found (DB or cache) and their `metadata.scim_active` is `False`, meaning the IdP deactivated the user via SCIM. LiteLLM refuses all keys owned by a SCIM-deactivated user even if the key itself is valid, unblocked, and unexpired.
Source
Thrown at litellm/proxy/auth/user_api_key_auth.py:1819
prisma_client=prisma_client,
user_api_key_cache=user_api_key_cache,
user_id_upsert=False,
parent_otel_span=parent_otel_span,
proxy_logging_obj=proxy_logging_obj,
)
except Exception as e:
verbose_logger.debug(
"litellm.proxy.auth.user_api_key_auth.py::user_api_key_auth() - Unable to get user from db/cache. Setting user_obj to None. Exception received - %s",
e,
)
user_obj = None
if (
user_obj is not None
and isinstance(user_obj.metadata, dict)
and user_obj.metadata.get("scim_active") is False
):
raise Exception(
f"User={valid_token.user_id} has been deactivated via SCIM. Keys owned by this user cannot be used."
)
# Check 2a. Check if model has zero cost - if so, skip all budget checks
model = _get_model_from_request_context(
request_data=request_data,
route=route,
request=request,
llm_router=llm_router,
)
skip_budget_checks = False
if model is not None and llm_router is not None:
from litellm.proxy.auth.auth_checks import _is_model_cost_zero
skip_budget_checks = _is_model_cost_zero(model=model, llm_router=llm_router)
if skip_budget_checks:
verbose_proxy_logger.info("Skipping all budget checks for zero-cost model: %s", model)
View on GitHub (pinned to 77b7c6c40c)
Solutions
- Re-activate the user in the IdP so SCIM sync sets `scim_active` true again (if the user should keep access)
- If the user should stay gone, migrate the workload to a new key owned by an active user/team (`/key/generate` with a valid user_id)
- As a proxy admin, clear/flip `metadata.scim_active` for the user record if SCIM state is stale and the deactivation was erroneous
Example fix
# before: cron uses departed employee's key -> 'deactivated via SCIM'
client = OpenAI(base_url=..., api_key=os.environ["DEPARTED_USER_KEY"])
# after: key owned by team/service identity
new_key = admin.post("/key/generate", json={"team_id": "svc-team"}).json()["key"]
client = OpenAI(base_url=..., api_key=new_key) Defensive patterns
Strategy: try-catch
Validate before calling
# before lending a user-owned key to automation, check the user is SCIM-active
user = admin.get(f"/user/info?user_id={uid}").json()
if user.get("metadata", {}).get("scim_active") is False:
raise PermissionError(f"user {uid} SCIM-deactivated; their keys are unusable") Type guard
def user_is_scim_active(user: dict) -> bool:
return user.get("metadata", {}).get("scim_active") is not False Try / catch
try:
client.chat.completions.create(...)
except Exception as e:
if "deactivated via SCIM" in str(e):
rotate_to_team_key() # move workload to an active identity's key
raise UserDeactivated from e
raise Prevention
- Bind long-running services to team/service keys, not individual user keys
- Coordinate SCIM offboarding with key rotation in the same runbook
- Surface SCIM deactivation errors to oncall, not just logs
When it happens
Trigger: IdP (Okta/Entra) deprovisions a user, SCIM sync sets `metadata.scim_active=false`; any of that user's keys are then used for any request — check 2's user lookup reads `scim_active` and raises. Re-activation requires SCIM setting it back or an admin clearing the flag.
Common situations: Employees offboarded but their service keys still embedded in cron jobs/notebooks; SCIM soft-delete semantics marking users inactive; test users disabled in the IdP during access reviews; ordering issue where SCIM deactivates before keys are rotated.
Related errors
- BFL initial request failed: {initial_response.text}
- No api key passed in.
- Malformed API Key passed in. Ensure Key has `Bearer ` prefix
- Tried to access route={route}, which is only for MASTER KEY
- Key is blocked. Update via `/key/unblock` if you're an admin
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/47a82acf9897e73e.
Report an issue: GitHub.