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

  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.