{"record":{"id":"fe8f19accc5c7bc3","repo":"deepset-ai/haystack","slug":"chatmessages-from-role-role-must-contain-text-r","errorCode":null,"errorMessage":"ChatMessages from {role} role must contain text. Received ChatMessage with no text: {message}","messagePattern":"ChatMessages from (.+?) role must contain text\\. Received ChatMessage with no text: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/builders/chat_prompt_builder.py","lineNumber":178,"sourceCode":"            `template` parameter. For example, to use more variables during prompt engineering than the ones present\n            in the default template, you can provide them here.\n        \"\"\"\n        self._variables = variables\n        self._required_variables = required_variables\n        self.template = template\n\n        self._env = HaystackSandboxedEnvironment(extensions=[ChatMessageExtension])\n        if arrow_import.is_successful():\n            self._env.add_extension(Jinja2TimeExtension)\n\n        extracted_variables = []\n        if template and not variables:\n            if isinstance(template, list):\n                for message in template:\n                    if message.is_from(ChatRole.USER) or message.is_from(ChatRole.SYSTEM):\n                        # infer variables from template\n                        if message.text is None:\n                            raise ValueError(NO_TEXT_ERROR_MESSAGE.format(role=message.role.value, message=message))\n                        if message.text and \"templatize_part\" in message.text:\n                            raise ValueError(FILTER_NOT_ALLOWED_ERROR_MESSAGE)\n                        assigned_variables, template_variables = _extract_template_variables_and_assignments(\n                            env=self._env, template=message.text\n                        )\n                        extracted_variables += list(template_variables - assigned_variables)\n            elif isinstance(template, str):\n                assigned_variables, template_variables = _extract_template_variables_and_assignments(\n                    env=self._env, template=template\n                )\n                extracted_variables = list(template_variables - assigned_variables)\n\n        extracted_variables = extracted_variables or []\n        self.variables = variables or extracted_variables\n        self.required_variables = required_variables or []\n\n        if len(self.variables) > 0 and required_variables is None:\n            logger.warning(","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/builders/chat_prompt_builder.py#L160-L196","documentation":"ChatPromptBuilder raises this in __init__ when a USER or SYSTEM ChatMessage passed as a Jinja template has text=None (e.g. a tool/function-call message with no textual content). Variable inference requires message.text to extract template variables, so the constructor fails fast.","triggerScenarios":"Passing template as a list of ChatMessage where any USER or SYSTEM message was built without text content (e.g. ChatMessage.from_function_call or an empty message), then instantiating ChatPromptBuilder(template=[...]).","commonSituations":"Building a prompt list from deserialized or programmatically constructed messages where tool-call payloads replaced the text; copying messages from a chat log where the first system message has no text.","solutions":["Ensure every USER/SYSTEM ChatMessage in the template list has non-None text (use ChatMessage.from_user(text=...) / from_system(text=...)).","Filter out messages without text before passing the list to ChatPromptBuilder.","If you need non-text content in a template, use a string template plus variables instead of ChatMessage objects."],"exampleFix":"// before\nmsg = ChatMessage.from_function_call(call_obj)\nprompt = ChatPromptBuilder(template=[msg])  # text is None\n// after\ntemplate = [m for m in messages if m.text is not None and m.is_from(ChatRole.USER) or m.is_from(ChatRole.SYSTEM)]\nprompt = ChatPromptBuilder(template=template)","handlingStrategy":"validation","validationCode":"from haystack.dataclasses import ChatRole\nmsgs = [m for m in template if m.text is not None or not (m.is_from(ChatRole.USER) or m.is_from(ChatRole.SYSTEM))]","typeGuard":"def has_text(m) -> bool:\n    return m.text is not None or not (m.is_from(ChatRole.USER) or m.is_from(ChatRole.SYSTEM))","tryCatchPattern":"try:\n    builder = ChatPromptBuilder(template=template)\nexcept ValueError as e:\n    if 'must contain text' in str(e):\n        template = [m for m in template if m.text is not None]\n        builder = ChatPromptBuilder(template=template)\n    else:\n        raise","preventionTips":["Always construct USER/SYSTEM messages with explicit text.","Filter deserialized chat histories for textless messages before templating.","Add an assert/self-check helper for template lists in your pipeline setup."],"tags":["validation","chat-prompt-builder","jinja-template"],"backgroundTag":"empty-template-text","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}