{"record":{"id":"48c50240ece6a340","repo":"microsoft/autogen","slug":"field-type-is-required-in-the-message-data-to-re","errorCode":null,"errorMessage":"Field 'type' is required in the message data to recover the message type.","messagePattern":"Field 'type' is required in the message data to recover the message type\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/messages.py","lineNumber":633,"sourceCode":"\n    def register(self, message_type: type[BaseAgentEvent | BaseChatMessage]) -> None:\n        \"\"\"Register a new message type with the factory.\"\"\"\n        if self.is_registered(message_type):\n            raise ValueError(f\"Message type {message_type} is already registered.\")\n        if not issubclass(message_type, BaseChatMessage) and not issubclass(message_type, BaseAgentEvent):\n            raise ValueError(f\"Message type {message_type} must be a subclass of BaseChatMessage or BaseAgentEvent.\")\n        # Get the class name of the\n        class_name = message_type.__name__\n        # Check if the class name is already registered.\n        # Register the message type.\n        self._message_types[class_name] = message_type\n\n    def create(self, data: Mapping[str, Any]) -> BaseAgentEvent | BaseChatMessage:\n        \"\"\"Create a message from a dictionary of JSON-serializable data.\"\"\"\n        # Get the type of the message from the dictionary.\n        message_type = data.get(\"type\")\n        if message_type is None:\n            raise ValueError(\"Field 'type' is required in the message data to recover the message type.\")\n        if message_type not in self._message_types:\n            raise ValueError(f\"Unknown message type: {message_type}\")\n        if not isinstance(message_type, str):\n            raise ValueError(f\"Message type must be a string, got {type(message_type)}\")\n\n        # Get the class for the message type.\n        message_class = self._message_types[message_type]\n\n        # Create an instance of the message class.\n        assert issubclass(message_class, BaseChatMessage) or issubclass(message_class, BaseAgentEvent)\n        return message_class.load(data)\n\n\nChatMessage = Annotated[\n    TextMessage | MultiModalMessage | StopMessage | ToolCallSummaryMessage | HandoffMessage,\n    Field(discriminator=\"type\"),\n]\n\"\"\"The union type of all built-in concrete subclasses of :class:`BaseChatMessage`.","sourceCodeStart":615,"sourceCodeEnd":651,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/messages.py#L615-L651","documentation":"Thrown by MessageFactory.create() when deserializing a message from a dict that has no 'type' key. Every message in AutoGen AgentChat round-trips through a discriminated-union scheme where the 'type' string (e.g. 'TextMessage', 'ToolCallSummaryMessage') selects the registered class to reconstruct. Without it the factory cannot know which class's load() to call.","triggerScenarios":"Calling MessageFactory.create(data) (directly or via team state loading / serialized checkpoint restore) with a dict missing the 'type' key, e.g. {'content': 'hi', 'source': 'user'}. Also occurs when a custom serialization path drops or renames the 'type' field before calling create().","commonSituations":"Restoring a team checkpoint saved with an older serialization format, hand-building message dicts for replay/testing, or a custom message class whose dump()/load() implementation forgets to include 'type'.","solutions":["Inspect the dict passed to create() and add the correct 'type' key matching a registered message class name (e.g. data['type'] = 'TextMessage').","If serializing messages yourself, use message.dump() instead of manually building the dict — dump() always emits 'type'.","If a custom message class is involved, verify its dump() override includes 'type': type(self).__name__ or equivalent.","If loading old saved state, re-save it with the current version or migrate the state file to include 'type' fields."],"exampleFix":"// before\nmsg = factory.create({\"content\": \"hi\", \"source\": \"user\"})  # ValueError\n\n// after\nmsg = factory.create({\"type\": \"TextMessage\", \"content\": \"hi\", \"source\": \"user\"})","handlingStrategy":"validation","validationCode":"def has_valid_type_field(data: Mapping[str, Any]) -> bool:\n    t = data.get(\"type\")\n    return isinstance(t, str) and len(t) > 0","typeGuard":"from typing import Any, Mapping\n\ndef is_serialized_message(data: Any) -> bool:\n    return isinstance(data, Mapping) and isinstance(data.get(\"type\"), str)","tryCatchPattern":"try:\n    msg = factory.create(data)\nexcept ValueError as e:\n    if \"'type' is required\" in str(e):\n        raise ValueError(f\"payload missing 'type': {data!r}\") from e\n    raise","preventionTips":["Always produce serialized messages with message.dump() rather than hand-built dicts.","When persisting messages, store the full dump() output including 'type'.","Add a schema check on loaded checkpoints before passing them to create()."],"tags":["python","autogen","serialization","message-factory","deserialization"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}