agentscope-ai/agentscope · error · ValueError

"AgentScopeLLM received no usable messages (empty list or al

Error message

"AgentScopeLLM received no usable messages (empty list or all roles unrecognized)."

What it means

generate_response converts mem0 messages to AgentScope Msg objects by role; if the input list is empty or every message has an unrecognized role, nothing survives conversion and the adapter raises rather than calling the model with no input.

Source

Thrown at src/agentscope/middleware/_longterm_memory/_mem0/_agentscope_adapter.py:136

            )
        self._agentscope_model: ChatModelBase = self.config.model
        self._bridge = _AsyncBridge()

    # ----- LLMBase interface -----
    # pylint: disable=unused-argument
    def generate_response(
        self,
        messages: list[dict[str, str]],
        response_format: Any | None = None,  # mem0 contract — unused
        tools: list[dict] | None = None,
        tool_choice: str = "auto",  # mem0 contract — unused
    ) -> str | dict:
        """mem0 ``LLMBase`` entry — runs the AgentScope chat model
        synchronously and returns str (or dict with tool_calls when
        ``tools`` is given)."""
        as_messages = _convert_messages_to_agentscope(messages)
        if not as_messages:
            raise ValueError(
                "AgentScopeLLM received no usable messages "
                "(empty list or all roles unrecognized).",
            )

        response = self._bridge.run(
            _await_chat(self._agentscope_model, as_messages, tools),
        )
        return _parse_chat_response(response, has_tool=bool(tools))


async def _await_chat(
    model: ChatModelBase,
    messages: list[Msg],
    tools: list[dict] | None,
) -> "ChatResponse":
    """Call the AgentScope chat model, handling both streaming and
    non-streaming returns."""
    result = await model(messages, tools=tools)

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Ensure at least one message with a standard role ('system', 'user', 'assistant') is passed
  2. Log the raw messages list before calling generate_response to spot empty/odd-role inputs
  3. If calling from custom code, guard with a length check before invoking the LLM

Example fix

// before
resp = llm.generate_response(messages)
// after
if not messages:
    raise ValueError('messages must not be empty')
resp = llm.generate_response(messages)
Defensive patterns

Strategy: validation

Validate before calling

us = _convert_messages_to_agentscope(messages) if hasattr(m, '_convert') else messages
if not messages or all(m.get('role') not in ('system','user','assistant','tool') for m in messages):
    raise ValueError('no usable messages')

Type guard

def has_usable_messages(msgs: list[dict]) -> bool:
    return any(isinstance(m, dict) and m.get('role') in {'system','user','assistant'} for m in msgs)

Try / catch

try:
    resp = llm.generate_response(messages)
except ValueError as e:
    if 'no usable messages' in str(e):
        messages = [{'role': 'user', 'content': fallback_prompt}]
        resp = llm.generate_response(messages)
    else:
        raise

Prevention

When it happens

Trigger: Calling AgentScopeLLM.generate_response([]) or with messages whose roles fall outside the mapped set (e.g. 'tool'/'function' roles that the converter doesn't recognize).

Common situations: mem0 internals stripping messages; custom pipelines building message lists dynamically that end up empty; role-name mismatches after a mem0 version change.

Related errors


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