deepset-ai/haystack · error · TypeError
Expected ChatMessage object, got {type(last_message)}
Error message
Expected ChatMessage object, got {type(last_message)} What it means
RegexTextExtractor processes the input list and expects its last element to be a ChatMessage. If the last element is any other type (e.g. a plain string or Document), _process_last_message raises TypeError naming the received type.
Source
Thrown at haystack/components/extractors/regex_text_extractor.py:122
logger.warning("Received empty list of messages")
return {"captured_text": ""}
return self._process_last_message(text_or_messages)
def _build_result(self, result: str | list[str]) -> dict:
"""Helper method to build the return dictionary based on configuration."""
if (isinstance(result, str) and result == "") or (isinstance(result, list) and not result):
return {"captured_text": ""}
return {"captured_text": result}
def _process_last_message(self, messages: list[ChatMessage]) -> dict:
"""
Process only the last message and build the result.
:raises TypeError: If the last element of the list is not a ChatMessage instance.
"""
last_message = messages[-1]
if not isinstance(last_message, ChatMessage):
raise TypeError(f"Expected ChatMessage object, got {type(last_message)}")
if last_message.text is None:
logger.warning("Last message has no text content")
return {"captured_text": ""}
result = self._extract_from_text(last_message.text)
return self._build_result(result)
def _extract_from_text(self, text: str) -> str | list[str]:
"""
Extract text using the regex pattern.
:param text:
The text to search through.
:returns:
The text captured by the first capturing group in the regex pattern.
If the pattern has no capture groups, returns the entire match.
If no match is found, returns an empty string.
"""View on GitHub (pinned to e318778c9b)
Solutions
- Ensure the input is a list whose last element is a ChatMessage, e.g. run(messages=[ChatMessage.from_user(text)])
- Convert strings before passing: ChatMessage.from_user(my_string)
- Check the upstream component's output type and add an adapter component if it emits non-ChatMessage values
Example fix
// before
extractor.run(messages=["some plain text"])
// after
from haystack.dataclasses import ChatMessage
extractor.run(messages=[ChatMessage.from_user("some plain text")]) Defensive patterns
Strategy: type-guard
Validate before calling
if not messages or not isinstance(messages[-1], ChatMessage):
raise TypeError("Last message must be a ChatMessage") Type guard
from haystack.dataclasses import ChatMessage
def is_chat_message_list(messages: list) -> bool:
return bool(messages) and isinstance(messages[-1], ChatMessage) Try / catch
try:
result = extractor.run(messages=messages)
except TypeError as e:
logger.error("RegexTextExtractor input error: %s", e)
raise Prevention
- Feed the extractor from chat-message-producing components only
- Wrap raw strings with ChatMessage.from_user before passing
- Check pipeline connection types to catch mismatched sockets at connect time
When it happens
Trigger: Calling run(messages=[...]) where messages[-1] is not a ChatMessage instance — e.g. feeding raw strings from a custom component, or an upstream component emitting Documents instead of chat messages.
Common situations: Connecting a non-chat component's output to the extractor; manually constructing test inputs as strings; migration from string-based to chat-message-based pipelines.
Related errors
- LLM evaluator expects all input values to be lists but recei
- Unsupported data source type: {type(source).__name__}
- Tool execution requires at least one tool.
- The {self.__class__.__name__} expects a list containing only
- Unsupported source type {type(source)}
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/54a88797552a4c42.
Report an issue: GitHub.