BerriAI/litellm · error · DeepKeepGuardrailAPIError
DeepKeep guardrail API failed: {error}
Error message
DeepKeep guardrail API failed: {error} What it means
Raised by the DeepKeep guardrail hook when its POST to the DeepKeep AI Firewall fails and no fail-open path applies. In _handle_guardrail_request_error it wraps httpx Timeout, RequestError, and HTTPStatusError from raise_for_status() — i.e. any status other than 502/503/504, or those gateway statuses when unreachable_fallback is 'fail_closed' (Timeout always takes is_unreachable=True). The underlying exception text is embedded in the message, and the proxy log line 'DeepKeep guardrail API error: <error>' carries the detail.
Source
Thrown at litellm/proxy/guardrails/guardrail_hooks/deepkeep/deepkeep.py:231
self,
error: Exception,
inputs: GenericGuardrailAPIInputs,
input_type: Literal["request", "response"],
logging_obj: Optional["LiteLLMLoggingObj"],
is_unreachable: bool = True,
) -> GenericGuardrailAPIInputs:
"""Handle errors from the DeepKeep API with fail-open/fail-closed logic."""
if is_unreachable and self.unreachable_fallback == "fail_open":
http_status_code: Final = getattr(getattr(error, "response", None), "status_code", None)
return self._fail_open_passthrough(
inputs=inputs,
input_type=input_type,
logging_obj=logging_obj,
error=error,
**({"http_status_code": http_status_code} if http_status_code else {}),
)
verbose_proxy_logger.error("DeepKeep guardrail API error: %s", str(error))
raise DeepKeepGuardrailAPIError(f"DeepKeep guardrail API failed: {error}")
@staticmethod
def _build_return_inputs(
*,
response_json: dict[str, Any],
texts: list,
images: Any | None,
tools: Any | None,
tool_calls: Any | None,
structured_messages: Any | None,
) -> GenericGuardrailAPIInputs:
"""Merge original inputs with any guardrail-modified values from the API response.
Presence is checked with ``is not None`` (not truthiness) so that an
intentional empty-list replacement such as ``texts: []`` or
``tool_calls: []`` is honoured and forwarded downstream rather than
silently discarded in favour of the original content.
"""View on GitHub (pinned to 77b7c6c40c)
Solutions
- Read the verbose proxy log line 'DeepKeep guardrail API error: <error>' to get the underlying status code and message.
- Verify DEEPKEEP_API_KEY, DEEPKEEP_API_BASE, and firewall_id by curl-ing the firewall endpoint directly with the same X-API-Key header.
- Set litellm_params: unreachable_fallback: fail_open in the guardrail config so 502/503/504 outages and timeouts pass traffic through instead of raising.
- If the key is valid but a 404 persists, confirm the firewall is deployed in the DeepKeep console and the firewall_id matches.
- Temporarily detach the deepkeep guardrail from guardrails-config to confirm the rest of the proxy is healthy.
Example fix
# before (config.yaml)
guardrails:
- guardrail_name: deepkeep
litellm_params:
guardrail: deepkeep
api_base: https://app.deepkeep.ai/firewall
unreachable_fallback: fail_closed
# after
guardrails:
- guardrail_name: deepkeep
litellm_params:
guardrail: deepkeep
api_base: https://app.deepkeep.ai/firewall
unreachable_fallback: fail_open Defensive patterns
Strategy: fallback
Validate before calling
import os
missing = [v for v in ('DEEPKEEP_API_KEY', 'DEEPKEEP_API_BASE') if not os.getenv(v)]
if missing:
raise SystemExit(f'deploy blocked, missing env: {missing}') Type guard
from litellm.proxy.guardrails.guardrail_hooks.deepkeep.deepkeep import DeepKeepGuardrailAPIError
def is_deepkeep_api_error(exc: BaseException) -> bool:
return isinstance(exc, DeepKeepGuardrailAPIError) Try / catch
from litellm.proxy.guardrails.guardrail_hooks.deepkeep.deepkeep import DeepKeepGuardrailAPIError
try:
result = await guardrail.apply_guardrail(inputs, request_data, 'request', logging_obj)
except DeepKeepGuardrailAPIError as e:
logger.warning('DeepKeep unreachable, failing open: %s', e)
result = dict(inputs) # proceed unmoderated (or re-raise in strict mode) Prevention
- Configure unreachable_fallback: fail_open unless your compliance posture requires fail-closed.
- Monitor the proxy log for 'DeepKeep guardrail API error' and alert on frequency spikes.
- Smoke-test api_base, API key, and firewall_id after every credential rotation.
When it happens
Trigger: DeepKeep returns 401/403 (invalid X-API-Key), 404 (wrong firewall_id or api_base path), 429, or 5xx while unreachable_fallback='fail_closed'; the firewall hostname fails DNS resolution; the request exceeds the httpx client timeout; the response body is not valid JSON after a 200.
Common situations: Expired or rotated DeepKeep API key; typo in DEEPKEEP_API_BASE; firewall_id that does not exist in the DeepKeep tenant; a DeepKeep outage with fail-open not configured, so every proxied LLM call fails while the guardrail endpoint is down.
Related errors
- Generic Guardrail API failed: {error}
- {exc}
- Failed to fetch provider mapping: {e}
- Content violates policy
- Failed to fetch prompt version '{prompt_version_id}': {e}
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/958edd8c5cecd733.
Report an issue: GitHub.