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

  1. Re-activate the user in the IdP so SCIM sync sets `scim_active` true again (if the user should keep access)
  2. 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)
  3. 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

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


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