{"record":{"id":"f75b8ad33a00d20b","repo":"microsoft/autogen","slug":"message-type-must-be-a-string-got-type-message-t","errorCode":null,"errorMessage":"Message type must be a string, got {type(message_type)}","messagePattern":"Message type must be a string, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/messages.py","lineNumber":637,"sourceCode":"            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`.\nIt does not include :class:`StructuredMessage` types.\"\"\"\n\nAgentEvent = Annotated[\n    ToolCallRequestEvent","sourceCodeStart":619,"sourceCodeEnd":655,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/messages.py#L619-L655","documentation":"Intended to be raised when data['type'] is not a string (e.g. an int or bytes). Note the guard order in the source: the 'not in self._message_types' check runs first, so any non-string value that isn't a registered key already raises 'Unknown message type' before this branch. In practice this error is nearly unreachable; seeing it means a non-string type value collided with a registry lookup.","triggerScenarios":"Calling MessageFactory.create() with data['type'] set to a non-string, non-None value (e.g. {'type': 5}) — though most such inputs actually fail earlier with 'Unknown message type' because registry keys are strings.","commonSituations":"Corrupted or externally produced message payloads where 'type' was encoded as a number or bytes; JSON-decoded data that went through a lossy transform.","solutions":["Coerce the field to a string before calling create(): data['type'] = str(data['type']).","Fix the upstream producer so it always writes 'type' as a JSON string.","If you hit this exact message (not 'Unknown message type'), audit any code that mutates the factory's _message_types registry with non-string keys."],"exampleFix":"# before\nfactory.create({\"type\": 5, \"content\": \"hi\"})\n\n# after\nfactory.create({\"type\": \"TextMessage\", \"content\": \"hi\"})","handlingStrategy":"validation","validationCode":"if not isinstance(data.get(\"type\"), str):\n    data = {**data, \"type\": str(data.get(\"type\"))}\nmsg = factory.create(data)","typeGuard":"def type_is_str(data: Mapping[str, Any]) -> bool:\n    return isinstance(data.get(\"type\"), str)","tryCatchPattern":null,"preventionTips":["Ensure message payloads come from message.dump() or validated JSON schemas.","Never mutate the factory registry with non-string keys.","Validate external payloads against a pydantic model with type: str before create()."],"tags":["python","autogen","message-factory","type-validation"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}