FoundationAgents/OpenManus · error · ValueError
The last message must be from the user to attach images
Error message
The last message must be from the user to attach images
What it means
Raised by LLM.ask_with_images() when, after formatting, the last message in the list is not role="user". Images are attached by mutating the final user message's content into a multimodal array, so the code requires that anchor point. A trailing assistant or system message makes attachment ambiguous and triggers this guard.
Source
Thrown at app/llm.py:528
TokenLimitExceeded: If token limits are exceeded
ValueError: If messages are invalid or response is empty
OpenAIError: If API call fails after retries
Exception: For unexpected errors
"""
try:
# For ask_with_images, we always set supports_images to True because
# this method should only be called with models that support images
if self.model not in MULTIMODAL_MODELS:
raise ValueError(
f"Model {self.model} does not support images. Use a model from {MULTIMODAL_MODELS}"
)
# Format messages with image support
formatted_messages = self.format_messages(messages, supports_images=True)
# Ensure the last message is from the user to attach images
if not formatted_messages or formatted_messages[-1]["role"] != "user":
raise ValueError(
"The last message must be from the user to attach images"
)
# Process the last user message to include images
last_message = formatted_messages[-1]
# Convert content to multimodal format if needed
content = last_message["content"]
multimodal_content = (
[{"type": "text", "text": content}]
if isinstance(content, str)
else content
if isinstance(content, list)
else []
)
# Add images to content
for image in images:View on GitHub (pinned to 52a13f2a57)
Solutions
- Append a user message before calling: messages.append(Message.user_message("Describe this image"))
- Strip trailing non-user messages from the history you pass in
- Ensure the list is non-empty — check len(messages) > 0 before the call
Example fix
# before
messages = [Message.system_message("you are helpful"), Message.assistant_message("hi")]
await llm.ask_with_images(messages, [img]) # ValueError
# after
messages.append(Message.user_message("describe this image"))
await llm.ask_with_images(messages, [img]) Defensive patterns
Strategy: validation
Validate before calling
def last_message_is_user(messages: list) -> bool:
return bool(messages) and getattr(messages[-1], "role", None) == "user" Prevention
- Always append a fresh user message before ask_with_images()
- Trim trailing assistant/system messages from reused histories
- Unit-test the message assembly step so role ordering cannot silently regress
When it happens
Trigger: Calling ask_with_images(messages) where messages ends with an assistant message (e.g. pre-populated dialogue), an empty list (formatted_messages is empty), or messages ending with a system message.
Common situations: Reusing a conversation history that ends with the model's last reply; injecting a system-style suffix after the user turn; passing [] accidentally.
Related errors
- Unsupported image format: {image}
- Model {self.model} does not support images. Use a model from
- Invalid tool_choice: {tool_choice}
- Server URL is required for SSE connection
- Command is required for stdio connection
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/cc1c60e9ef0f2ae6.
Report an issue: GitHub.