microsoft/autogen · error · ValueError

No content in the last message

Error message

No content in the last message

What it means

The assistant's last message was found but its content attribute is empty/None, so there is no text to turn into a chat message. The agent refuses to return an empty response and raises rather than emitting a blank TextMessage.

Source

Thrown at python/packages/autogen-ext/src/autogen_ext/agents/azure/_azure_ai_agent.py:810

        ):
            if cancellation_token.is_cancelled():
                trace_logger.debug("Message retrieval cancelled by token.")
                break
            agent_messages.append(msg)
            if len(agent_messages) >= message_limit:
                break
        if not agent_messages:
            raise ValueError("No messages received from assistant")

        # Get the last message from the agent (role=AGENT)
        last_message: Optional[ThreadMessage] = next(
            (m for m in agent_messages if getattr(m, "role", None) == "agent"), None
        )
        if not last_message:
            trace_logger.debug("No message with AGENT role found, falling back to first message")
            last_message = agent_messages[0]  # Fallback to first message
        if not getattr(last_message, "content", None):
            raise ValueError("No content in the last message")

        # Extract text content
        message_text = ""
        for text_message in last_message.text_messages:
            message_text += text_message.text.value

        # Extract citations
        citations: list[Any] = []

        # Try accessing annotations directly

        annotations = getattr(last_message, "annotations", [])

        if isinstance(annotations, list) and annotations:
            annotations = cast(List[MessageTextUrlCitationAnnotation], annotations)

            trace_logger.debug(f"Found {len(annotations)} annotations")
            for annotation in annotations:

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Retry the turn — often transient when the service is still committing messages; add a small delay before on_messages when polling showed a just-completed run.
  2. Inspect the thread via the raw SDK to see the actual message shapes and confirm the run truly produced text.
  3. If the run only performed tool calls, send a follow-up turn so the model produces a textual reply.
  4. Upgrade autogen-ext; last-message selection logic has evolved.
Defensive patterns

Strategy: retry

Try / catch

try:
    resp = await agent.on_messages(msgs, ct)
except ValueError as e:
    if "No content in the last message" in str(e):
        await asyncio.sleep(1)
        resp = await agent.on_messages(msgs, ct)  # one retry
    else:
        raise

Prevention

When it happens

Trigger: A thread message whose content is an empty list/None — e.g. a message that only carried tool_call metadata, or a message partially deleted; the role-based fallback picks agent_messages[0] which may also be contentless.

Common situations: Runs that end immediately after tool calls (the tool-call message has no content); message truncation on the service side; racing with deletion/cleanup of thread messages.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/f611a1bb5b7f66ae. Report an issue: GitHub.