BerriAI/litellm · error · HTTPException
Microsoft Purview DLP: Responses API input could not be tran
Error message
Microsoft Purview DLP: Responses API input could not be transformed for DLP scanning in blocking mode
What it means
Fail-closed HTTPException from the Purview pre-call hook for /v1/responses requests. Before scanning, the guardrail converts the Responses API 'input' into chat messages via LiteLLMCompletionResponsesConfig.transform_responses_api_input_to_messages; if that transform raises for the given input shape, blocking mode cannot guarantee coverage, so the request is rejected with 400 rather than silently bypassing DLP.
Source
Thrown at litellm/proxy/guardrails/guardrail_hooks/microsoft_purview/purview_dlp.py:324
input_data: Final = data.get("input")
if input_data is None and not data.get("instructions"):
return None
try:
# Always transform via messages so ``instructions`` become a system message
# (string ``input`` alone would skip instructions and bypass DLP).
messages: Final = LiteLLMCompletionResponsesConfig.transform_responses_api_input_to_messages(
input=input_data if input_data is not None else "",
responses_api_request=data,
)
return self.get_prompt_text_for_dlp(cast(list[Any], messages))
except Exception:
verbose_proxy_logger.warning(
"Purview DLP: failed to transform responses API input",
exc_info=True,
)
if raise_on_failure:
raise HTTPException(
status_code=400,
detail={
"error": (
"Microsoft Purview DLP: Responses API input could "
"not be transformed for DLP scanning in blocking mode"
),
},
)
return None
# ------------------------------------------------------------------
# Identity resolution for blocking modes
# ------------------------------------------------------------------
def _resolve_user_id_for_blocking(
self,
data: dict[str, Any],
user_api_key_dict: Any,View on GitHub (pinned to 77b7c6c40c)
Solutions
- Simplify the Responses API input: use a plain string or the standard, well-supported items shapes and retest
- Upgrade litellm to the latest patch so the responses->messages transformer covers more input types
- If it persists, capture the logged traceback ('Purview DLP: failed to transform responses API input' warning with exc_info) and file an issue with a minimal input payload
- As a workaround for non-sensitive traffic, route those calls to a deployment without the Purview guardrail attached — do not disable blocking globally
Example fix
# before: exotic input shape
resp = client.responses.create(
model="gpt-4o",
input=[{"type":"item_reference", "id": "item_abc"}],
)
# after: plain well-formed input the DLP scan can transform
resp = client.responses.create(
model="gpt-4o",
input=[{"role": "user", "content": "Summarize the quarterly report"}],
) Defensive patterns
Strategy: validation
Validate before calling
# Client-side: sanity-check Responses API input shape before sending through guarded routes
SUPPORTED_ITEM_TYPES = {"message", "function_call", "function_call_output", "reasoning"}
def responses_input_scannable(inp) -> bool:
if isinstance(inp, str):
return True
if isinstance(inp, list):
return all(
isinstance(i, dict) and i.get("type") in SUPPORTED_ITEM_TYPES
for i in inp
)
return False Type guard
def is_plain_responses_input(x: object) -> bool:
"""True for string or standard item shapes the DLP transform handles."""
if isinstance(x, str):
return True
if isinstance(x, list):
return all(isinstance(i, dict) and i.get("type") in {"message"} for i in x)
return False Try / catch
try:
resp = client.responses.create(model=m, input=inp)
except BadRequestError as e:
if "could not be transformed for DLP scanning" in str(e):
simplify_input_and_retry(inp) # fall back to plain string input
raise Prevention
- Pin the shapes you send to documented Responses API item types; avoid exotic/typed content blocks on guarded routes
- Add contract tests that send your real payload shapes through a staging proxy with the guardrail enabled
- Keep litellm patched so the responses->messages transformer gains new input types
When it happens
Trigger: Calling /v1/responses through the proxy with an unusual or malformed items array in 'input' (unsupported item/typed-content types), with guardrail mode including pre_call and blocking enabled; None input where the fallback empty-string path also fails; a litellm version whose transformer does not yet support a newer Responses API input type
Common situations: Adopting the Responses API alongside a recently added Purview guardrail; sending function/tool outputs or nested typed content blocks the transformer cannot flatten; upgrading one side (proxy vs client SDK) so accepted input shapes drift
Related errors
- Microsoft Purview DLP: No proxy-authenticated user identity;
- Microsoft Purview DLP: Token-id completion prompts cannot be
- Microsoft Purview: tenant_id is required
- Microsoft Purview: client_id is required
- Microsoft Purview: client_secret (or api_key) is required
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/0f1bd850f11d9ad2.
Report an issue: GitHub.