alibaba/spring-ai-alibaba · warning
The tool returned an empty AssistantMessage. Converting to…
Error message
The tool returned an empty AssistantMessage. Converting to conventional response.
What it means
MessageToolCallResultConverter converts a tool's return value into a string for ToolResponseMessage. An AssistantMessage with empty text (and no media) carries no usable content, so the converter logs this warning and returns the conventional JSON '"Done"' response.
Solutions
- Return a non-empty string or ToolResponseMessage from the tool instead of an empty AssistantMessage
- Check text before constructing AssistantMessage and fall back to a meaningful placeholder
- Handle media separately — media in AssistantMessage throws UnsupportedOperationException here
- Log/inspect the tool pipeline to find why the wrapped generation returned empty text
Example fix
// before
return new AssistantMessage(""); // warns, becomes "Done"
// after
String text = generate();
return new AssistantMessage(text != null && !text.isBlank() ? text : "No content generated"); Defensive patterns
Strategy: validation
Validate before calling
if (toolResult instanceof AssistantMessage am && (am.getText() == null || am.getText().isBlank()) && (am.getMedia() == null || am.getMedia().isEmpty())) { log.warn("Tool produced empty AssistantMessage"); } Type guard
static boolean hasUsableText(AssistantMessage m) { return m != null && m.getText() != null && !m.getText().isBlank(); } Prevention
- Return plain Strings or ToolResponseMessage from tools rather than raw AssistantMessage
- Validate LLM output for emptiness inside tools before wrapping
- Never put media in AssistantMessage returned to this converter (it throws UnsupportedOperationException)
When it happens
Trigger: A @Tool-annotated method (or ToolCallback) returns an AssistantMessage whose getText() is empty/blank and getMedia() is empty, e.g. new AssistantMessage("").
Common situations: Tool wraps an LLM call that returned empty content; tool builds AssistantMessage programmatically with null/blank text; upstream model outage yields empty message passed through as tool result.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/4eea30fba4e9bb1a.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/MessageToolCallResultConverter.java:49
public class MessageToolCallResultConverter implements ToolCallResultConverter {
private static final Logger logger = LoggerFactory.getLogger(MessageToolCallResultConverter.class);
/**
* Currently Spring AI ToolResponseMessage only supports text type, that's why the return type of this method is String.
* More types like image/audio/video/file can be supported in the future.
*/
public String convert(@Nullable Object result, @Nullable Type returnType) {
if (returnType == Void.TYPE) {
logger.debug("The tool has no return type. Converting to conventional response.");
return JsonParser.toJson("Done");
} else if (result instanceof AssistantMessage assistantMessage) {
if (StringUtils.hasLength(assistantMessage.getText())) {
return assistantMessage.getText();
} else if (CollectionUtils.isNotEmpty(assistantMessage.getMedia())) {
throw new UnsupportedOperationException("Currently Spring AI ToolResponseMessage only supports text type, that's why the return type of this method is String. More types like image/audio/video/file can be supported in the future.");
}
logger.warn("The tool returned an empty AssistantMessage. Converting to conventional response.");
return JsonParser.toJson("Done");
} else {
logger.debug("Converting tool result to JSON.");
return JsonParser.toJson(result);
}
}
}
View on GitHub (pinned to f82da0b50f)