langchain-ai/langchain · error · ValueError
Unrecognized content block at messages[{i}].content[{j}] has
Error message
Unrecognized content block at messages[{i}].content[{j}] has 'type': 'guard_content' but does not have a messages[{i}].content[{j}]['guard_content']['text'] key. Full content block:
{block} What it means
The converter recognizes a `"guard_content"` dialect (used for LanGuardian-style guarded text): the block must contain `guard_content` and that nested dict must contain `text` (either a string or `{"text": ...}`). If either is missing, the guard text cannot be extracted and the block is rejected with this error. The check fires both when `type == "guard_content"` lacks the key entirely and when the nested `text` is absent.
Source
Thrown at libs/core/langchain_core/messages/utils.py:1911
content.append(
{
"type": "text",
"text": json.dumps(block["json"]),
}
)
elif (block.get("type") == "guard_content") or "guard_content" in block:
if (
"guard_content" not in block
or "text" not in block["guard_content"]
):
msg = (
f"Unrecognized content block at "
f"messages[{i}].content[{j}] has 'type': "
f"'guard_content' but does not have a "
f"messages[{i}].content[{j}]['guard_content']['text'] "
f"key. Full content block:\n\n{block}"
)
raise ValueError(msg)
text = block["guard_content"]["text"]
if isinstance(text, dict):
text = text["text"]
content.append({"type": "text", "text": text})
# VertexAI format
elif block.get("type") == "media":
if missing := [k for k in ("mime_type", "data") if k not in block]:
err = (
f"Unrecognized content block at "
f"messages[{i}].content[{j}] has 'type': "
f"'media' but does not have key(s) {missing}. Full "
f"content block:\n\n{block}"
)
raise ValueError(err)
if "image" not in block["mime_type"]:
err = (
f"OpenAI messages can only support text and image data."
f" Received content block with media of type:"View on GitHub (pinned to e32fa9a52e)
Solutions
- Emit the full shape: `{"type": "guard_content", "guard_content": {"type": "text", "text": "..."}}` (nested `text` as a plain string also works).
- If moderation is not needed, remove the block rather than leaving a stub.
- Pin/verify the middleware version whose guard-block schema matches what `langchain-core` expects.
Example fix
// before
{"type": "guard_content", "guard_content": {"type": "text"}}
// after
{"type": "guard_content", "guard_content": {"type": "text", "text": "guarded payload"}} Defensive patterns
Strategy: validation
Validate before calling
def valid_guard_block(b: dict) -> bool:
gc = b.get("guard_content")
return isinstance(gc, dict) and (
isinstance(gc.get("text"), str)
or isinstance(gc.get("text"), dict) and "text" in gc["text"]
)
blocks = [b for b in blocks if b.get("type") != "guard_content" or valid_guard_block(b)] Type guard
def is_guard_content_block(b: dict) -> bool:
return (
(b.get("type") == "guard_content" or "guard_content" in b)
and isinstance(b.get("guard_content"), dict)
and "text" in b["guard_content"]
) Prevention
- Pin the moderation middleware version and test its emitted schema
- If moderation is disabled, ensure no stub guard blocks remain in history
- Cover guard blocks in your message-round-trip tests
When it happens
Trigger: `{"type": "guard_content"}` with no `guard_content` key; `{"guard_content": {"type": "text"}}` where the nested payload omits `text`; guard blocks produced by a middleware version with a different schema.
Common situations: Integrating content-moderation middleware that emits `guard_content` blocks; upgrading the middleware after its schema changed; hand-crafting guard blocks in tests.
Related errors
- Unrecognized content block at messages[{i}].content[{j}] has
- Unrecognized content block at messages[{i}].content[{j}] has
- Unrecognized content block at messages[{i}].content[{j}] has
- Unrecognized content block at messages[{i}].content[{j}] has
- Unrecognized content block at messages[{i}].content[{j}] doe
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/931468b4b538a282.
Report an issue: GitHub.