BerriAI/litellm · error · HTTPException

Content blocked: MCP tool result structuredContent is nested

Error message

Content blocked: MCP tool result structuredContent is nested too deeply to be scanned by the configured guardrail

What it means

The guardrail scanner hit its nesting-depth ceiling while serializing an MCP tool result's structuredContent for scanning. Rather than letting unscannable content reach the client, the request is blocked — a safety cutoff, not a data bug.

Source

Thrown at litellm/proxy/_experimental/mcp_server/guardrail_translation/handler.py:133

        ``structuredContent`` is scanned and masked too, in the same
        ``apply_guardrail`` call: it is serialized to the client alongside
        ``content``, so a value living only there would otherwise reach the
        client unscanned.
        """
        content: Final = mcp_tool_result_content_list(response)
        text_blocks: Final = (
            tuple(
                (index, text) for index, item in enumerate(content) if (text := mcp_content_item_text(item)) is not None
            )
            if content is not None
            else ()
        )

        structured: Final = mcp_tool_result_structured_content(response)
        structured_leaves: Final = json_string_leaves(structured) if structured is not None else ()
        structured_labels: Final = json_unrewritable_labels(structured) if structured is not None else ()
        if structured_leaves is None or structured_labels is None:
            raise HTTPException(
                status_code=400,
                detail={
                    "error": (
                        "Content blocked: MCP tool result structuredContent is nested too deeply to be scanned "
                        "by the configured guardrail"
                    )
                },
            )

        if not text_blocks and not structured_leaves and not structured_labels:
            verbose_proxy_logger.debug("MCP Guardrail: tool result has no scannable text, nothing to do")
            return response

        originals: Final = (
            tuple(text for _, text in text_blocks) + tuple(text for _, text in structured_leaves) + structured_labels
        )
        guardrailed_inputs: Final = await guardrail_to_apply.apply_guardrail(
            inputs=GenericGuardrailAPIInputs(texts=list(originals)),

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Reduce nesting depth of structuredContent, or raise the guardrail scan depth limit.

Example fix

Flatten structuredContent or configure a deeper scan limit.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at litellm/proxy/_experimental/mcp_server/guardrail_translation/handler.py:133 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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