{"record":{"id":"c296010294b2c905","repo":"deepset-ai/haystack","slug":"stateschema-type-for-key-param-must-be-a-py","errorCode":null,"errorMessage":"StateSchema: 'type' for key '{param}' must be a Python type, got {definition['type']}","messagePattern":"StateSchema: 'type' for key '(.+?)' must be a Python type, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/agents/state/state.py","lineNumber":71,"sourceCode":"\n    return deserialized_schema\n\n\ndef _validate_schema(schema: dict[str, Any]) -> None:\n    \"\"\"\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:","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/agents/state/state.py#L53-L89","documentation":"StateSchema validation raises this ValueError when the 'type' entry of a schema key is not recognized as a valid Python type by _is_valid_type (e.g. a string like 'list' or an arbitrary object instead of an actual type).","triggerScenarios":"Passing {\"param\": {\"type\": \"list\"}} (string instead of type), or a non-type value like a dict or instance as the 'type' entry.","commonSituations":"Serializing schemas to JSON (types become strings) and loading them back without conversion, or confusing typing annotations like List[int] patterns unsupported by _is_valid_type.","solutions":["Use the actual Python type object: list, not \"list\"","If the schema was JSON-serialized, map string names back to types on load (e.g. via a lookup dict)","Verify the value with isinstance(value, type) before constructing StateSchema"],"exampleFix":"// before\nschema = {\"numbers\": {\"type\": \"list\"}}\n// after\nschema = {\"numbers\": {\"type\": list}}","handlingStrategy":"type-guard","validationCode":"def types_are_types(schema):\n    return all(isinstance(d.get(\"type\"), type) or\n               (hasattr(d.get(\"type\"), \"__origin__\")) for d in schema.values())","typeGuard":"def is_real_type(t) -> bool:\n    import types, typing\n    return isinstance(t, type) or typing.get_origin(t) is not None","tryCatchPattern":"try:\n    schema = StateSchema(my_schema)\nexcept ValueError as e:\n    if \"must be a Python type\" in str(e):\n        my_schema = {k: {**v, \"type\": TYPE_LOOKUP[str(v['type'])]} for k, v in my_schema.items()}\n    else:\n        raise","preventionTips":["Use type objects (list, list[ChatMessage]) not their string names","Don't round-trip schemas through JSON without remapping types","Check with isinstance(v, type) before building the schema"],"tags":["python","schema-validation","agent","state","types"],"backgroundTag":"schema-validation-failed","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}