alibaba/spring-ai-alibaba · error · UnsupportedOperationException
Currently Spring AI ToolResponseMessage only supports text…
Error message
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.
What it means
MessageToolCallResultConverter.convert throws UnsupportedOperationException when a tool returns an AssistantMessage that has media (image/audio/video/file) content but no text, because Spring AI's ToolResponseMessage only supports String (text) tool results.
Solutions
- Return a String from the tool (e.g. a URL, base64, or textual description of the media) instead of a media-bearing AssistantMessage.
- If returning AssistantMessage, ensure setText/description carries non-empty text alongside media.
- Return a Map/POJO and let the converter JSON-serialize it instead of using AssistantMessage.
Example fix
// before
return new AssistantMessage("", List.of(new Media(MimeTypeUtils.IMAGE_PNG, url)));
// after
return "Generated image available at " + url; Defensive patterns
Strategy: type-guard
Validate before calling
if (result instanceof AssistantMessage am && !am.hasText() && CollectionUtils.isNotEmpty(am.getMedia())) {
throw new IllegalStateException("Tool returns media-only AssistantMessage; return a String instead");
} Type guard
static boolean isTextOnlyResult(Object r) {
return !(r instanceof AssistantMessage am) || (StringUtils.hasLength(am.getText()) || CollectionUtils.isEmpty(am.getMedia()));
} Try / catch
try { result = tool.call(args, ctx); } catch (UnsupportedOperationException e) { result = describeMediaAsText(toolResult); } Prevention
- Have tools return String or simple POJOs, not AssistantMessage with media.
- Document that Spring AI tool results are text-only in this converter.
- Wrap media outputs as URLs or descriptions in the tool itself.
When it happens
Trigger: A @Tool method (or tool callback) returns an AssistantMessage whose media list is non-empty and whose text is empty; the converter then cannot produce a String result for the ToolResponseMessage.
Common situations: Wrapping a multimodal model output or generated image in an AssistantMessage and returning it from a tool; porting tools that returned richer content types from other frameworks.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- A2aRemoteAgent has not support schedule.
- cancel is not implemented yet!
- Edge ' ' is parallel
- Failed to read resource
- LoopAgent must have only one subAgent, please use…
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/bf0360702d592d81.
Report an issue: GitHub.
Appendix: source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/MessageToolCallResultConverter.java:47
import org.slf4j.LoggerFactory;
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)