agentscope-ai/agentscope · error · TypeError

Input must be a list of Msg objects.

Error message

Input must be a list of Msg objects.

What it means

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.

Source

Thrown at src/agentscope/formatter/_formatter_base.py:61

            for t in self.input_types
            if t not in ("text/plain", "application/x-thinking")
        ]

    @abstractmethod
    async def format(self, *args: Any, **kwargs: Any) -> list[dict[str, Any]]:
        """Format the Msg objects to a list of dictionaries that satisfy the
        API requirements."""

    @staticmethod
    def assert_list_of_msgs(msgs: list[Msg]) -> None:
        """Assert that the input is a list of Msg objects.

        Args:
            msgs (`list[Msg]`):
                A list of Msg objects to be validated.
        """
        if not isinstance(msgs, list):
            raise TypeError("Input must be a list of Msg objects.")

        for msg in msgs:
            if not isinstance(msg, Msg):
                raise TypeError(
                    f"Expected Msg object, got {type(msg)} instead.",
                )

    @staticmethod
    def _convert_unsupported_data_block_to_string(block: DataBlock) -> str:
        """Convert an unsupported data block into its textual fallback.

        URL sources remain accessible through their URL. Base64 sources are
        persisted to a temporary file so the model can still reference the
        result when the target API cannot carry that media type directly.

        Args:
            block (`DataBlock`):
                The unsupported data block to convert.

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Wrap a single message in a list: formatter.format([msg])
  2. If msgs is a generator/tuple, convert with list(msgs)
  3. Ensure every element is a Msg instance (reconstruct from dicts via Msg.from_dict or similar if deserializing)

Example fix

# before
formatter.format(msg)

# after
formatter.format([msg])
Defensive patterns

Strategy: validation

Validate before calling

msgs = [msg] if isinstance(msg, Msg) else msgs
assert isinstance(msgs, list), "formatter.format expects list[Msg]"

Type guard

def is_msg_list(msgs) -> bool:
    return isinstance(msgs, list) and all(isinstance(m, Msg) for m in msgs)

Try / catch

try:
    formatter.format(msgs)
except TypeError as e:
    if "list of Msg" in str(e):
        msgs = [msg] if not isinstance(msgs, list) else list(msgs)
        formatted = formatter.format(msgs)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/ae00082cfd880014. Report an issue: GitHub.