agentscope-ai/agentscope · error · ValueError

The input messages cannot be empty for the…

Error message

The input messages cannot be empty for the `generate_structured_output` method.

What it means

generate_structured_output requires a non-empty messages list; calling it with [] raises this ValueError immediately. The messages provide the prompt context the model needs to produce structured output, so an empty list is rejected upfront.

Solutions

  1. Pass at least one message, typically the instruction prompt: generate_structured_output([Msg('user', 'extract fields: ...')], Schema)
  2. Guard the call site: if not messages: skip or supply a default prompt
  3. Log the message list length before calling to find where it becomes empty

Example fix

# before
res = await model.generate_structured_output([], Schema)

# after
res = await model.generate_structured_output(
    [Msg('user', 'Extract the fields from the given text.')], Schema)
Defensive patterns

Strategy: validation

Validate before calling

if not messages:
    raise ValueError('nothing to structure')  # or supply a default prompt
res = await model.generate_structured_output(messages, Schema)

Type guard

def has_messages(msgs: list) -> bool:
    return isinstance(msgs, list) and len(msgs) > 0

Prevention

When it happens

Trigger: Calling model.generate_structured_output([], MySchema) or passing a messages list that was built from an empty conversation / filtered to nothing.

Common situations: Programmatically building a message list from user input that turns out empty; slicing history incorrectly (e.g. messages[10:]) so the list is empty; refactoring a call path that previously checked length.

Related errors


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

Appendix: source

Thrown at src/agentscope/model/_base.py:493

        - ``no_think``: thinking disabled + forced ``tool_choice`` (skipped
          when the provider exposes no thinking toggle)
        - ``none``: current config + no ``tool_choice``

        An explicit ``tool_choice`` in ``kwargs`` bypasses the strategy
        ladder and is forwarded unchanged.

        Args:
            messages (`list[Msg]`):
                The context for LLM to generate the structured output.
            structured_model (`Type[BaseModel] | dict`):
                A Pydantic model or a dict of JSON schemas.

        Returns:
            `StructuredResponse`:
                The structured response generated by the model.
        """
        if len(messages) == 0:
            raise ValueError(
                "The input messages cannot be empty for the "
                "`generate_structured_output` method.",
            )

        user_tool_choice = kwargs.pop("tool_choice", None)
        if user_tool_choice is None:
            forced_tc = ToolChoice(mode="generate_structured_output")
            disable_kwargs = self._get_disable_thinking_kwargs()
            # (name, extra `_call_api` kwargs, tool_choice), best first.
            # The no-think strategy only applies when the provider can
            # toggle it.
            strategies = (
                ("forced", {}, forced_tc),
                ("auto", {}, ToolChoice(mode="auto")),
                *(
                    (("no_think", disable_kwargs, forced_tc),)
                    if disable_kwargs
                    else ()

View on GitHub (pinned to e90f1c7592)