langchain-ai/langchain · error · ValueError

Unrecognized content block at messages[{i}].content[{j}] doe

Error message

Unrecognized content block at messages[{i}].content[{j}] does not match OpenAI, Anthropic, Bedrock Converse, or VertexAI format. Full content block:

{block}

What it means

This is the terminal `else` of the content-block dispatch in `convert_to_openai_messages`: the block matched none of the recognized dialects (OpenAI text/image_url/file, Anthropic, Bedrock Converse, tool_use/tool_result, json, guard_content, media) and is not a `thinking`/`reasoning` block. Rather than silently dropping or forwarding unknown data to the OpenAI API, the converter raises. If the flag `pass_through_unknown_blocks=True` was set, unknown blocks would instead be passed through — the fact you see this error means that flag was not enabled (or the block fell in a branch that does not honor it).

Source

Thrown at libs/core/langchain_core/messages/utils.py:1954

                            "type": "image_url",
                            "image_url": {
                                "url": (f"data:{block['mime_type']};base64,{b64_image}")
                            },
                        }
                    )
                elif (
                    block.get("type") in {"thinking", "reasoning"}
                    or pass_through_unknown_blocks
                ):
                    content.append(block)
                else:
                    err = (
                        f"Unrecognized content block at "
                        f"messages[{i}].content[{j}] does not match OpenAI, "
                        f"Anthropic, Bedrock Converse, or VertexAI format. Full "
                        f"content block:\n\n{block}"
                    )
                    raise ValueError(err)
            if text_format == "string" and not any(
                block["type"] != "text" for block in content
            ):
                content = "\n".join(block["text"] for block in content)
        oai_msg["content"] = content
        if message.content and not oai_msg["content"] and tool_messages:
            oai_messages.extend(tool_messages)
        else:
            oai_messages.extend([oai_msg, *tool_messages])

    if is_single:
        return oai_messages[0]
    return oai_messages


def _first_max_tokens(
    messages: Sequence[BaseMessage],
    *,

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Check the echoed `block` in the error: fix the `type` tag to a supported value (`text`, `image_url`, `image`, `tool_use`, `tool_result`, `json`, `guard_content`, `media`, `file`).
  2. If the block is legitimately non-standard and your target tolerates it, pass `pass_through_unknown_blocks=True` to `convert_to_openai_messages`.
  3. Map custom block types to `text` blocks (`{"type": "text", "text": json.dumps(block)}`) before conversion.
  4. Reasoning blocks must use `thinking` or `reasoning` as the type to be passed through.

Example fix

// before
convert_to_openai_messages([HumanMessage(content=[{"type": "txt", "txt": "hi"}])])

// after
convert_to_openai_messages([HumanMessage(content=[{"type": "text", "text": "hi"}])])
Defensive patterns

Strategy: validation

Validate before calling

KNOWN_TYPES = {"text", "image_url", "image", "file", "tool_use", "tool_result", "json", "guard_content", "media", "thinking", "reasoning"}

def unrecognized(block) -> bool:
    return isinstance(block, dict) and block.get("type") not in KNOWN_TYPES

bad = [b for b in blocks if unrecognized(b)]
if bad:
    raise ValueError(f"unsupported blocks: {bad}")

Type guard

def is_known_content_block(b: dict) -> bool:
    return b.get("type") in {"text", "image_url", "image", "file", "tool_use", "tool_result", "json", "guard_content", "media", "thinking", "reasoning"}

Try / catch

try:
    oai = convert_to_openai_messages(messages)
except ValueError:
    # opt into passthrough if the target provider tolerates the block
    oai = convert_to_openai_messages(messages, pass_through_unknown_blocks=True)

Prevention

When it happens

Trigger: Typos in the type tag (`"txt"`, `"Image"`, `"image-url"`); proprietary block types from other frameworks (e.g. Cohere/Gemini-specific shapes); blocks that are plain strings where dicts are expected can also fall through depending on surrounding handling.

Common situations: Feeding raw provider responses from unsupported providers into the converter; schema drift after a partner package update introduced new block types; copy-paste of example payloads with subtle type-name errors.

Related errors


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