{"record":{"id":"7607393dded2e873","repo":"langchain-ai/langchain","slug":"unrecognized-content-block-at-messages-i-conten","errorCode":null,"errorMessage":"Unrecognized content block at messages[{i}].content[{j}] has 'type': 'text' but is missing expected key(s) {missing}. Full content block:\\n\\n{block}","messagePattern":"Unrecognized content block at messages\\[(.+?)\\]\\.content\\[(.+?)\\] has 'type': 'text' but is missing expected key\\(s\\) (.+?)\\. Full content block:\\\\n\\\\n(.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/messages/utils.py","lineNumber":1697,"sourceCode":"            content = \"\\n\".join(\n                block if isinstance(block, str) else block[\"text\"]\n                for block in message.content\n            )\n        else:\n            content = []\n            for j, block in enumerate(message.content):\n                # OpenAI format\n                if isinstance(block, str):\n                    content.append({\"type\": \"text\", \"text\": block})\n                elif block.get(\"type\") == \"text\":\n                    if missing := [k for k in (\"text\",) if k not in block]:\n                        err = (\n                            f\"Unrecognized content block at \"\n                            f\"messages[{i}].content[{j}] has 'type': 'text' \"\n                            f\"but is missing expected key(s) \"\n                            f\"{missing}. Full content block:\\n\\n{block}\"\n                        )\n                        raise ValueError(err)\n                    content.append({\"type\": block[\"type\"], \"text\": block[\"text\"]})\n                elif block.get(\"type\") == \"image_url\":\n                    if missing := [k for k in (\"image_url\",) if k not in block]:\n                        err = (\n                            f\"Unrecognized content block at \"\n                            f\"messages[{i}].content[{j}] has 'type': 'image_url' \"\n                            f\"but is missing expected key(s) \"\n                            f\"{missing}. Full content block:\\n\\n{block}\"\n                        )\n                        raise ValueError(err)\n                    content.append(\n                        {\n                            \"type\": \"image_url\",\n                            \"image_url\": block[\"image_url\"],\n                        }\n                    )\n                # Standard multi-modal content block\n                elif is_data_content_block(block):","sourceCodeStart":1679,"sourceCodeEnd":1715,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/messages/utils.py#L1679-L1715","documentation":"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.","triggerScenarios":"A content block like `{'type': 'text'}` or `{'type': 'text', 'value': 'hi'}` inside a message passed to `convert_to_openai_messages` (with block-typed content).","commonSituations":"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.","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"],"exampleFix":"# before\nconvert_to_openai_messages([HumanMessage([{'type': 'text', 'value': 'hi'}])])\n\n# after\nconvert_to_openai_messages([HumanMessage([{'type': 'text', 'text': 'hi'}])])","handlingStrategy":"validation","validationCode":"def valid_text_block(b: dict) -> bool:\n    return b.get('type') == 'text' and isinstance(b.get('text'), str)\n\nblocks = [b for b in content if not (isinstance(b, dict) and b.get('type') == 'text') or valid_text_block(b)]","typeGuard":"def is_wellformed_text_block(b: object) -> bool:\n    return isinstance(b, dict) and b.get('type') == 'text' and isinstance(b.get('text'), str)","tryCatchPattern":"try:\n    oai = convert_to_openai_messages(msgs)\nexcept ValueError as e:\n    if \"has 'type': 'text'\" in str(e):\n        raise ValueError(f'fix source block: {e}') from e  # fail loudly with indices\n    raise","preventionTips":["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"],"tags":["openai","content-blocks","multimodal","input-validation"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}