BerriAI/litellm · error · DeepKeepGuardrailMissingSecrets

DeepKeep API base URL is required. Set the `DEEPKEEP_API_BAS

Error message

DeepKeep API base URL is required. Set the `DEEPKEEP_API_BASE` environment variable or pass `api_base` in the guardrail config.

What it means

DeepKeepGuardrailMissingSecrets raised by DeepKeepGuardrail.__init__ when no API base URL is available: neither the api_base argument nor the DEEPKEEP_API_BASE environment variable is set. The constructor then normalizes whatever base it gets (trailing slash stripped, the guardrail endpoint path appended if missing), so you only need to supply the plain tenant base URL.

Source

Thrown at litellm/proxy/guardrails/guardrail_hooks/deepkeep/deepkeep.py:97

        if not deepkeep_api_key:
            raise DeepKeepGuardrailMissingSecrets(
                "DeepKeep API key is required. Set the `DEEPKEEP_API_KEY` environment "
                "variable or pass `api_key` in the guardrail config."
            )
        self.deepkeep_api_key: str = deepkeep_api_key

        # Firewall ID
        self.firewall_id = firewall_id or os.environ.get("DEEPKEEP_FIREWALL_ID")
        if not self.firewall_id:
            raise DeepKeepGuardrailMissingSecrets(
                "DeepKeep firewall_id is required. Set the `DEEPKEEP_FIREWALL_ID` environment "
                "variable or pass `deepkeep_firewall_id` in the guardrail config."
            )

        # API base URL
        base_url = api_base or os.environ.get("DEEPKEEP_API_BASE")
        if not base_url:
            raise DeepKeepGuardrailMissingSecrets(
                "DeepKeep API base URL is required. Set the `DEEPKEEP_API_BASE` environment "
                "variable or pass `api_base` in the guardrail config."
            )

        # Normalize the API base – ensure it ends with the guardrail endpoint
        base_url = base_url.rstrip("/")
        if base_url.endswith(_DEEPKEEP_GUARDRAIL_ENDPOINT.rstrip("/")):
            self.api_base = base_url
        else:
            self.api_base = f"{base_url}{_DEEPKEEP_GUARDRAIL_ENDPOINT}"

        self.unreachable_fallback: Literal["fail_closed", "fail_open"] = unreachable_fallback
        if extra_headers is not None and not isinstance(extra_headers, Mapping):
            verbose_proxy_logger.warning(
                "DeepKeep guardrail ignoring `extra_headers`: expected a mapping of header name to value, got %s. "
                "`litellm_params.extra_headers` is a list of header names to forward and is not supported by this guardrail",
                type(extra_headers).__name__,
            )

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Set DEEPKEEP_API_BASE to your DeepKeep tenant base URL (scheme + host; the guardrail endpoint path is appended automatically) and restart the proxy
  2. Or add api_base: os.environ/DEEPKEEP_API_BASE under litellm_params
  3. Do not manually append the guardrail endpoint path — the code appends it when missing, and appending twice is handled, but keep it simple
  4. Verify network reachability of the base URL from the proxy container

Example fix

# before
guardrails:
  - guardrail_id: deepkeep
    litellm_params:
      mode: guardrail_runs_before_llm_call
      api_key: os.environ/DEEPKEEP_API_KEY
      deepkeep_firewall_id: os.environ/DEEPKEEP_FIREWALL_ID

# after
# export DEEPKEEP_API_BASE=https://your-tenant.deepkeep.ai
guardrails:
  - guardrail_id: deepkeep
    litellm_params:
      mode: guardrail_runs_before_llm_call
      api_key: os.environ/DEEPKEEP_API_KEY
      deepkeep_firewall_id: os.environ/DEEPKEEP_FIREWALL_ID
      api_base: os.environ/DEEPKEEP_API_BASE
Defensive patterns

Strategy: validation

Validate before calling

import os
from urllib.parse import urlparse

base = os.environ.get('DEEPKEEP_API_BASE')
if not base or not urlparse(base).scheme or not urlparse(base).netloc:
    raise RuntimeError('DEEPKEEP_API_BASE must be set to a full URL (scheme + host)')

Try / catch

from litellm.proxy.guardrails.guardrail_hooks.deepkeep.deepkeep import DeepKeepGuardrailMissingSecrets
try:
    guardrail = DeepKeepGuardrail(
        guardrail_name='deepkeep',
        api_key=os.environ['DEEPKEEP_API_KEY'],
        firewall_id=os.environ['DEEPKEEP_FIREWALL_ID'],
    )
except DeepKeepGuardrailMissingSecrets as e:
    raise SystemExit(f'guardrail config incomplete: {e}') from e

Prevention

When it happens

Trigger: A deepkeep guardrails entry that supplies api_key and firewall_id but omits api_base while DEEPKEEP_API_BASE is unset in the proxy environment.

Common situations: Only key and firewall ID carried over from an example; per-environment base URL missing in prod manifests; pointing at the wrong tenant region host.

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/78ca9374ab6284cf. Report an issue: GitHub.