alibaba/spring-ai-alibaba · error · UnsupportedOperationException
Currently Spring AI ToolResponseMessage only supports text t
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.
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)
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.
- LoopAgent must have only one subAgent, please use subAgent()
- Failed to read resource
- cancel is not implemented yet!
- Edge '%s' is parallel
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/bf0360702d592d81.
Report an issue: GitHub.