BerriAI/litellm · error · ValueError

Microsoft Purview: tenant_id is required

Error message

Microsoft Purview: tenant_id is required

What it means

Config-time ValueError raised by the microsoft_purview guardrail's initialize_guardrail() in the LiteLLM proxy. The Purview DLP integration authenticates to Microsoft Entra ID (client-credentials OAuth), which requires an explicit tenant_id, client_id, and client_secret; there is no environment-variable fallback for tenant_id. The error means the guardrail entry in your proxy config had no 'tenant_id' under litellm_params.

Source

Thrown at litellm/proxy/guardrails/guardrail_hooks/microsoft_purview/__init__.py:22

from .purview_dlp import MicrosoftPurviewDLPGuardrail

if TYPE_CHECKING:
    from litellm.types.guardrails import Guardrail, LitellmParams


def initialize_guardrail(litellm_params: "LitellmParams", guardrail: "Guardrail"):
    import litellm

    tenant_id: Final = getattr(litellm_params, "tenant_id", None)
    client_id: Final = getattr(litellm_params, "client_id", None)

    # client_secret can be passed via the standard api_key field or as
    # a dedicated client_secret parameter.
    client_secret: Final = litellm_params.api_key or getattr(litellm_params, "client_secret", None)

    if not tenant_id:
        raise ValueError("Microsoft Purview: tenant_id is required")
    if not client_id:
        raise ValueError("Microsoft Purview: client_id is required")
    if not client_secret:
        raise ValueError("Microsoft Purview: client_secret (or api_key) is required")

    guardrail_name: Final = guardrail.get("guardrail_name")
    if not guardrail_name:
        raise ValueError("Microsoft Purview: guardrail_name is required")

    purview_guardrail: Final = MicrosoftPurviewDLPGuardrail(
        guardrail_name=guardrail_name,
        tenant_id=str(tenant_id),
        client_id=str(client_id),
        client_secret=str(client_secret),
        purview_app_name=str(getattr(litellm_params, "purview_app_name", None) or "LiteLLM"),
        user_id_field=str(getattr(litellm_params, "user_id_field", None) or "user_id"),
        event_hook=litellm_params.mode,
        default_on=litellm_params.default_on,

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Add 'tenant_id' inside the litellm_params block of that guardrail entry — the Azure tenant GUID shown in Entra ID > App registrations > Overview
  2. While editing, also set client_id and client_secret in the same block so init does not fail on the next check
  3. Restart the LiteLLM proxy so initialize_guardrail re-runs against the fixed config

Example fix

# before (config.yaml)
guardrails:
  - guardrail_name: purview-dlp
    litellm_params:
      guardrail: microsoft_purview
      mode: pre_call

# after
guardrails:
  - guardrail_name: purview-dlp
    litellm_params:
      guardrail: microsoft_purview
      mode: pre_call
      tenant_id: "11111111-2222-3333-4444-555555555555"
      client_id: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
      client_secret: "your-app-secret-value"
Defensive patterns

Strategy: validation

Validate before calling

# Run before starting the proxy: validate every microsoft_purview guardrail entry
import yaml

cfg = yaml.safe_load(open("config.yaml"))
for g in cfg.get("guardrails", []):
    lp = g.get("litellm_params", {})
    if lp.get("guardrail") == "microsoft_purview":
        missing = [k for k in ("tenant_id", "client_id", "client_secret") if not lp.get(k) and not (k == "client_secret" and lp.get("api_key"))]
        if not g.get("guardrail_name"):
            missing.insert(0, "guardrail_name(top-level)")
        if missing:
            raise SystemExit(f"purview guardrail '{g.get('guardrail_name', '<unnamed>')}' missing: {missing}")

Try / catch

# Startup-time: let config errors fail fast and loudly, don't swallow them
try:
    initialize_purview_guardrail_from(cfg)
except ValueError as e:
    if str(e).startswith("Microsoft Purview:"):
        log.fatal("bad guardrail config: %s", e)
        sys.exit(2)
    raise

Prevention

When it happens

Trigger: Declaring a guardrail with litellm_params.guardrail: microsoft_purview in config.yaml but omitting tenant_id, or setting it to an empty string/null (the check is falsy-based). Also a key typo such as tenantId or tenant-id, or placing the key at the wrong nesting level (sibling of litellm_params instead of inside it).

Common situations: Copying a Purview example config without filling in Azure values; assuming LiteLLM reads AZURE_TENANT_ID from env (it does not); migrating from another Azure guardrail whose config schema put credentials at the top level; hitting this only after adding mode: pre_call which actually instantiates the guardrail at proxy startup.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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