{"record":{"id":"f811adcaf84a323f","repo":"run-llama/llama_index","slug":"unsupported-message-content-type-type-bank-messa","errorCode":null,"errorMessage":"Unsupported message content type: {type(bank_message.content)}","messagePattern":"Unsupported message content type: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/prompts/rich.py","lineNumber":127,"sourceCode":"                        llama_blocks.append(ImageBlock(url=bank_block.image_url.url))\n                    elif bank_block.type == BanksContentBlockType.audio:\n                        llama_blocks.append(AudioBlock(url=bank_block.input_audio.data))\n                    elif bank_block.type == BanksContentBlockType.video:\n                        llama_blocks.append(VideoBlock(url=bank_block.input_video.data))\n                    elif bank_block.type == BanksContentBlockType.document:\n                        llama_blocks.append(\n                            DocumentBlock(url=bank_block.input_document.data)\n                        )\n                    else:\n                        raise ValueError(\n                            f\"Unsupported content block type: {bank_block.type}\"\n                        )\n\n                llama_messages.append(\n                    ChatMessage(role=bank_message.role, content=llama_blocks)\n                )\n            else:\n                raise ValueError(\n                    f\"Unsupported message content type: {type(bank_message.content)}\"\n                )\n\n        if self.output_parser is not None:\n            llama_messages = self.output_parser.format_messages(llama_messages)\n\n        return llama_messages\n\n    def get_template(self, llm: Optional[BaseLLM] = None) -> str:\n        return self.template_str\n","sourceCodeStart":109,"sourceCodeEnd":138,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/prompts/rich.py#L109-L138","documentation":"The message-level counterpart in rich.py: RichContext.format_messages() accepts bank messages whose content is either a plain string or a list of content blocks. Anything else (an int, a dict, a single block object instead of a list, custom objects) hits ValueError(f\"Unsupported message content type: {type(bank_message.content)}\"). The check is on the Python type of the content attribute, before per-block conversion even starts.","triggerScenarios":"Constructing a bank/message object with content=dict(...) or content=SomeBlock(...) (a single block, not a list), or content=None, then calling RichPromptTemplate.format(...) / rich_context.format_messages(...). Only str and list-of-blocks content pass the isinstance checks.","commonSituations":"Hand-building messages for Rich templates instead of using the provided helpers; dataclasses/pydantic v2 models whose attributes auto-coerce; content loaded from JSON where a block ended up as a raw dict instead of a typed block object.","solutions":["Make content a plain string for text-only messages: bank_message(role='user', content='hello').","Or make content a list of typed block objects: content=[TextBlock(text='hello'), ImageBlock(url=...)] — never a single unwrapped block or a dict.","If content comes from serialized data, parse dicts into the proper block classes before formatting.","Normalize defensively: wrap non-list, non-str content (or None) into [TextBlock(text=str(content))] before passing it in, if losing structure is acceptable."],"exampleFix":"# before\nmsg = bank_message(role=\"user\", content={\"text\": \"hi\"})     # dict -> ValueError\nmsg2 = bank_message(role=\"user\", content=TextBlock(text=\"hi\"))  # bare block -> ValueError\n\n# after\nmsg = bank_message(role=\"user\", content=\"hi\")                  # str is fine\nmsg2 = bank_message(role=\"user\", content=[TextBlock(text=\"hi\")])  # list of blocks is fine","handlingStrategy":"type-guard","validationCode":"def assert_bank_message_content(msg) -> None:\n    c = msg.content\n    if not isinstance(c, (str, list)):\n        raise TypeError(\n            f\"message content must be str or list of blocks, got {type(c).__name__}\" \n        )","typeGuard":"def has_formattable_content(msg) -> bool:\n    \"\"\"True when rich.py can convert this message (str or list content).\"\"\"\n    return isinstance(msg.content, str) or isinstance(msg.content, list)","tryCatchPattern":null,"preventionTips":["Always build bank messages with str or list-of-typed-blocks content.","When loading messages from serialized data, reconstruct typed block objects instead of leaving dicts.","Never pass a single bare block or dict as content — wrap in a list and use the proper block class."],"tags":["llama-index","rich","content-type","multimodal","input-validation"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}