{"record":{"id":"ae00082cfd880014","repo":"agentscope-ai/agentscope","slug":"input-must-be-a-list-of-msg-objects","errorCode":null,"errorMessage":"Input must be a list of Msg objects.","messagePattern":"Input must be a list of Msg objects\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/agentscope/formatter/_formatter_base.py","lineNumber":61,"sourceCode":"            for t in self.input_types\n            if t not in (\"text/plain\", \"application/x-thinking\")\n        ]\n\n    @abstractmethod\n    async def format(self, *args: Any, **kwargs: Any) -> list[dict[str, Any]]:\n        \"\"\"Format the Msg objects to a list of dictionaries that satisfy the\n        API requirements.\"\"\"\n\n    @staticmethod\n    def assert_list_of_msgs(msgs: list[Msg]) -> None:\n        \"\"\"Assert that the input is a list of Msg objects.\n\n        Args:\n            msgs (`list[Msg]`):\n                A list of Msg objects to be validated.\n        \"\"\"\n        if not isinstance(msgs, list):\n            raise TypeError(\"Input must be a list of Msg objects.\")\n\n        for msg in msgs:\n            if not isinstance(msg, Msg):\n                raise TypeError(\n                    f\"Expected Msg object, got {type(msg)} instead.\",\n                )\n\n    @staticmethod\n    def _convert_unsupported_data_block_to_string(block: DataBlock) -> str:\n        \"\"\"Convert an unsupported data block into its textual fallback.\n\n        URL sources remain accessible through their URL. Base64 sources are\n        persisted to a temporary file so the model can still reference the\n        result when the target API cannot carry that media type directly.\n\n        Args:\n            block (`DataBlock`):\n                The unsupported data block to convert.","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/formatter/_formatter_base.py#L43-L79","documentation":"The formatter base class validates that input is strictly a Python list of Msg objects; passing a single Msg, a tuple, a generator, or a list containing anything else raises this TypeError. It is a precondition check in assert_list_of_msgs, called by format()/_format_messages(). The library requires this exact shape because it iterates and formats each Msg.","triggerScenarios":"Calling formatter.format(single_msg) instead of format([single_msg]); passing msgs=conversation.messages when it's a tuple/generator; passing a list of dicts or strings.","commonSituations":"Reusing code written for APIs that accept a single message; wrapping history in a tuple or generator comprehension; feeding raw dicts from a serialized conversation.","solutions":["Wrap a single message in a list: formatter.format([msg])","If msgs is a generator/tuple, convert with list(msgs)","Ensure every element is a Msg instance (reconstruct from dicts via Msg.from_dict or similar if deserializing)"],"exampleFix":"# before\nformatter.format(msg)\n\n# after\nformatter.format([msg])","handlingStrategy":"validation","validationCode":"msgs = [msg] if isinstance(msg, Msg) else msgs\nassert isinstance(msgs, list), \"formatter.format expects list[Msg]\"","typeGuard":"def is_msg_list(msgs) -> bool:\n    return isinstance(msgs, list) and all(isinstance(m, Msg) for m in msgs)","tryCatchPattern":"try:\n    formatter.format(msgs)\nexcept TypeError as e:\n    if \"list of Msg\" in str(e):\n        msgs = [msg] if not isinstance(msgs, list) else list(msgs)\n        formatted = formatter.format(msgs)\n    else:\n        raise","preventionTips":["Always call format() with a list literal, even for one message","Convert generators/tuples with list() before formatting"],"tags":["validation","typeerror","formatter","agentscope","message"],"backgroundTag":"invalid-argument-type","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}