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 key 'image', but 'image' is missing expected key(s) {missing}. Full content block:
{block} What it means
Thrown by `convert_to_openai_messages` in `langchain_core.messages.utils` when a content block uses the Bedrock Converse image shape (`{"type": "image", "image": {...}}`) but the inner `image` dict is missing required keys. The converter requires both `source` (with `bytes`) and `format` before it can build an OpenAI `image_url` data-URI block, and it refuses to guess. The offending block is echoed in the message so you can see exactly which keys are absent.
Source
Thrown at libs/core/langchain_core/messages/utils.py:1761
"url": (
f"data:{source['media_type']};"
f"{source['type']},{source['data']}"
)
},
}
)
# Bedrock converse
elif image := block.get("image"):
if missing := [
k for k in ("source", "format") if k not in image
]:
err = (
f"Unrecognized content block at "
f"messages[{i}].content[{j}] has key 'image', "
f"but 'image' is missing expected key(s) "
f"{missing}. Full content block:\n\n{block}"
)
raise ValueError(err)
b64_image = _bytes_to_b64_str(image["source"]["bytes"])
content.append(
{
"type": "image_url",
"image_url": {
"url": (
f"data:image/{image['format']};base64,{b64_image}"
)
},
}
)
else:
err = (
f"Unrecognized content block at "
f"messages[{i}].content[{j}] has 'type': 'image' "
f"but does not have a 'source' or 'image' key. Full "
f"content block:\n\n{block}"
)View on GitHub (pinned to e32fa9a52e)
Solutions
- Make the image block match Bedrock Converse shape: `{"type": "image", "image": {"format": "png"|"jpeg"|"gif"|"webp", "source": {"bytes": <raw bytes or b64 str>}}}`.
- Or convert to native OpenAI shape instead: `{"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}}`, which the converter passes through without key checks.
- If relaying messages from an external system, validate/repair blocks in a pre-processing step before calling `convert_to_openai_messages`.
- Wrap the call in try/except ValueError to surface which message index (i, j) is malformed and fail that request with context.
Example fix
// before
content = [{"type": "image", "image": {"format": "png", "bytes": raw}}]
// after
content = [{
"type": "image",
"image": {"format": "png", "source": {"bytes": raw}},
}]
// or OpenAI native:
content = [{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}}] Defensive patterns
Strategy: validation
Validate before calling
def valid_bedrock_image(block: dict) -> bool:
img = block.get("image")
return (
isinstance(img, dict)
and "format" in img
and isinstance(img.get("source"), dict)
and "bytes" in img["source"]
)
# before conversion
for i, m in enumerate(messages):
for j, b in enumerate(m.content if isinstance(m.content, list) else []):
if b.get("type") == "image" and "image" in b and not valid_bedrock_image(b):
raise ValueError(f"malformed image block at messages[{i}].content[{j}]: {b}") Try / catch
try:
oai = convert_to_openai_messages(messages)
except ValueError as e:
# error text names messages[i].content[j]; use it to locate and repair the block
log.error("conversion failed: %s", e)
raise Prevention
- Centralize image-block construction in one helper that always emits the full Bedrock shape
- Never round-trip image blocks through lossy JSON that can drop nested keys
- Write unit tests asserting the exact block shape before calling convert_to_openai_messages
When it happens
Trigger: Passing a message whose content contains `{"type": "image", "image": {"format": "png"}}` (no `source`), or `{"image": {"source": {"bytes": b"..."}}}` (no `format`), to `convert_to_openai_messages()`. Also triggered when hand-building Bedrock Converse payloads or relaying raw Bedrock output that was truncated/mutated before conversion.
Common situations: Porting prompts written for `boto3` Bedrock `converse` into LangChain/LangGraph pipelines; constructing image blocks from dicts where the base64 bytes were placed at the top level instead of under `source.bytes`; partial serialization that drops nested keys.
Related errors
- Unrecognized content block at messages[{i}].content[{j}] doe
- 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
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/c89d2a6b18bccbbc.
Report an issue: GitHub.