langchain-ai/langchain · error · ValueError

Unrecognized content block at messages

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.

Solutions

  1. Make the image block match Bedrock Converse shape: `{"type": "image", "image": {"format": "png"|"jpeg"|"gif"|"webp", "source": {"bytes": <raw bytes or b64 str>}}}`.
  2. 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.
  3. If relaying messages from an external system, validate/repair blocks in a pre-processing step before calling `convert_to_openai_messages`.
  4. 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

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


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/c89d2a6b18bccbbc. Report an issue: GitHub.

Appendix: 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)