{"record":{"id":"2823a5489e99ddae","repo":"deepset-ai/haystack","slug":"stateschema-messages-must-be-of-type-list-chatm","errorCode":null,"errorMessage":"StateSchema: 'messages' must be of type list[ChatMessage], got {definition['type']}","messagePattern":"StateSchema: 'messages' must be of type list\\[ChatMessage\\], got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/agents/state/state.py","lineNumber":76,"sourceCode":"    \"\"\"\n    Validate that a schema dictionary meets all required constraints.\n\n    Checks that each parameter definition has a valid type field and that any handler\n    specified is a callable function.\n\n    :param schema: Dictionary mapping parameter names to their type and handler configs\n    :raises ValueError: If schema validation fails due to missing or invalid fields\n    \"\"\"\n    for param, definition in schema.items():\n        if \"type\" not in definition:\n            raise ValueError(f\"StateSchema: Key '{param}' is missing a 'type' entry.\")\n        if not _is_valid_type(definition[\"type\"]):\n            raise ValueError(f\"StateSchema: 'type' for key '{param}' must be a Python type, got {definition['type']}\")\n        if definition.get(\"handler\") is not None and not callable(definition[\"handler\"]):\n            raise ValueError(f\"StateSchema: 'handler' for key '{param}' must be callable or None\")\n        if param == \"messages\":  # definition[\"type\"] != list[ChatMessage] but split to cover also List[ChatMessage]\n            if not _is_list_type(definition[\"type\"]):\n                raise ValueError(f\"StateSchema: 'messages' must be of type list[ChatMessage], got {definition['type']}\")\n            # Check if the list contains ChatMessage elements\n            args = get_args(definition[\"type\"])\n            if not args or not issubclass(args[0], ChatMessage):\n                raise ValueError(f\"StateSchema: 'messages' must be of type list[ChatMessage], got {definition['type']}\")\n\n\nclass State:\n    \"\"\"\n    State is a container for storing shared information during the execution of an Agent and its tools.\n\n    For instance, State can be used to store documents, context, and intermediate results.\n\n    Internally it wraps a `_data` dictionary defined by a `schema`. Each schema entry has:\n    ```json\n      \"parameter_name\": {\n        \"type\": SomeType,  # expected type\n        \"handler\": Optional[Callable[[Any, Any], Any]]  # merge/update function\n      }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/agents/state/state.py#L58-L94","documentation":"StateSchema validation raises this ValueError when the special 'messages' key is declared with a type that is not a list type. The reserved 'messages' parameter must be list-typed because the Agent stores conversation history there.","triggerScenarios":"Defining schema={\"messages\": {\"type\": ChatMessage}} or {\"type\": str} — any non-list type for the 'messages' key.","commonSituations":"Copy-pasting a generic schema entry for 'messages', or intending to store a single ChatMessage instead of the required list.","solutions":["Declare messages as list[ChatMessage]: {\"messages\": {\"type\": list[ChatMessage]}}","Use typing.List[ChatMessage] if using older typing style — both are accepted","Never declare 'messages' as a scalar type"],"exampleFix":"// before\nschema = {\"messages\": {\"type\": ChatMessage}}\n// after\nschema = {\"messages\": {\"type\": list[ChatMessage]}}","handlingStrategy":"validation","validationCode":"from haystack.dataclasses import ChatMessage\ndef messages_key_valid(schema):\n    t = schema.get(\"messages\", {}).get(\"type\")\n    import typing\n    return t is None or (typing.get_origin(t) is list)","typeGuard":"import typing\nfrom haystack.dataclasses import ChatMessage\ndef is_message_list_type(t) -> bool:\n    return typing.get_origin(t) in (list,) and \\\n           typing.get_args(t) and typing.get_args(t)[0] is ChatMessage","tryCatchPattern":"try:\n    schema = StateSchema(my_schema)\nexcept ValueError as e:\n    if \"'messages' must be of type\" in str(e):\n        my_schema[\"messages\"][\"type\"] = list[ChatMessage]\n    else:\n        raise","preventionTips":["Always declare messages as list[ChatMessage]","Use the canonical schema constant if the library exposes one","Never declare 'messages' with a scalar type"],"tags":["python","schema-validation","agent","state","messages"],"backgroundTag":"schema-validation-failed","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}