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': 'text' but is missing expected key(s) {missing}. Full content block:\n\n{block} What it means
Raised by `convert_to_openai_messages` while iterating content blocks: a block declares `'type': 'text'` but is missing the required 'text' key. The converter needs the actual string to emit `{'type': 'text', 'text': ...}` and reports the message/block indices plus the full block.
Source
Thrown at libs/core/langchain_core/messages/utils.py:1697
content = "\n".join(
block if isinstance(block, str) else block["text"]
for block in message.content
)
else:
content = []
for j, block in enumerate(message.content):
# OpenAI format
if isinstance(block, str):
content.append({"type": "text", "text": block})
elif block.get("type") == "text":
if missing := [k for k in ("text",) if k not in block]:
err = (
f"Unrecognized content block at "
f"messages[{i}].content[{j}] has 'type': 'text' "
f"but is missing expected key(s) "
f"{missing}. Full content block:\n\n{block}"
)
raise ValueError(err)
content.append({"type": block["type"], "text": block["text"]})
elif block.get("type") == "image_url":
if missing := [k for k in ("image_url",) if k not in block]:
err = (
f"Unrecognized content block at "
f"messages[{i}].content[{j}] has 'type': 'image_url' "
f"but is missing expected key(s) "
f"{missing}. Full content block:\n\n{block}"
)
raise ValueError(err)
content.append(
{
"type": "image_url",
"image_url": block["image_url"],
}
)
# Standard multi-modal content block
elif is_data_content_block(block):View on GitHub (pinned to e32fa9a52e)
Solutions
- Ensure text blocks carry the 'text' key: `{'type': 'text', 'text': '...'}`
- Normalize provider-specific block shapes to the standard schema before converting
- Use the error's messages[i].content[j] indices to locate the offending block quickly
Example fix
# before
convert_to_openai_messages([HumanMessage([{'type': 'text', 'value': 'hi'}])])
# after
convert_to_openai_messages([HumanMessage([{'type': 'text', 'text': 'hi'}])]) Defensive patterns
Strategy: validation
Validate before calling
def valid_text_block(b: dict) -> bool:
return b.get('type') == 'text' and isinstance(b.get('text'), str)
blocks = [b for b in content if not (isinstance(b, dict) and b.get('type') == 'text') or valid_text_block(b)] Type guard
def is_wellformed_text_block(b: object) -> bool:
return isinstance(b, dict) and b.get('type') == 'text' and isinstance(b.get('text'), str) Try / catch
try:
oai = convert_to_openai_messages(msgs)
except ValueError as e:
if "has 'type': 'text'" in str(e):
raise ValueError(f'fix source block: {e}') from e # fail loudly with indices
raise Prevention
- Build text blocks with the exact {'type': 'text', 'text': ...} shape
- Validate multimodal content with a small schema check before conversion
- Use the messages[i].content[j] indices in the error to jump to the bad block
When it happens
Trigger: A content block like `{'type': 'text'}` or `{'type': 'text', 'value': 'hi'}` inside a message passed to `convert_to_openai_messages` (with block-typed content).
Common situations: Hand-assembled multimodal content with the wrong key name ('value', 'content', 'data'); blocks produced by another provider's schema and not normalized; template slots where 'text' was never filled.
Related errors
- Unrecognized content block at messages[{i}].content[{j}] has
- Unrecognized content block at messages[{i}].content[{j}] has
- mime_type key is required for base64 data.
- Unsupported source type. Only 'url' and 'base64' are support
- Keys base64, url, or file_id required for file blocks.
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/7607393dded2e873.
Report an issue: GitHub.