alibaba/spring-ai-alibaba · error · IllegalArgumentException
Unsupported DTO type:
Error message
Unsupported DTO type:
What it means
MessageDTOFactory.toMessage is the inverse of fromMessage: it maps known MessageDTO implementations (ToolRequestMessageDTO, AssistantMessageDTO, UserMessageDTO, ToolResponseMessageDTO) back into Spring AI Message objects. A MessageDTO of any other concrete type — notably ToolRequestConfirmMessageDTO, which exists in the Jackson @JsonSubTypes registry for human-in-the-loop confirmations but has no reverse mapping — triggers this IllegalArgumentException. The exception message includes the offending class name.
Source
Thrown at spring-ai-alibaba-studio/src/main/java/com/alibaba/cloud/ai/agent/studio/dto/messages/MessageDTO.java:130
public static Message toMessage(MessageDTO dto) {
if (dto == null) {
return null;
}
if (dto instanceof ToolRequestMessageDTO) {
return ((ToolRequestMessageDTO) dto).toAssistantMessage();
}
else if (dto instanceof AssistantMessageDTO) {
return ((AssistantMessageDTO) dto).toAssistantMessage();
}
else if (dto instanceof UserMessageDTO) {
return ((UserMessageDTO) dto).toUserMessage();
}
else if (dto instanceof ToolResponseMessageDTO) {
return ((ToolResponseMessageDTO) dto).toToolResponseMessage();
}
else {
throw new IllegalArgumentException(
"Unsupported DTO type: " + dto.getClass().getName()
);
}
}
}
}
View on GitHub (pinned to f82da0b50f)
Solutions
- Skip ToolRequestConfirmMessageDTO (and other non-reversible DTOs) when rebuilding Messages from DTO maps — filter them out before calling toMessage.
- Store the original Message alongside the DTO if you need a faithful round trip through confirm/interruption flows.
- If a reverse conversion is genuinely needed, add a branch in MessageDTOFactory.toMessage for the reported DTO type (e.g., convert ToolRequestConfirmMessageDTO back to ToolResponseMessage or drop it).
- Never instantiate custom MessageDTO implementations for state that will be converted back via toMessage.
Example fix
// before
Map<String, Message> msgs = new HashMap<>();
dtos.forEach((k, dto) -> msgs.put(k, MessageDTO.MessageDTOFactory.toMessage(dto))); // throws on ToolRequestConfirmMessageDTO
// after
dtos.forEach((k, dto) -> {
if (dto instanceof ToolRequestConfirmMessageDTO) return; // not convertible to a Message
msgs.put(k, MessageDTO.MessageDTOFactory.toMessage(dto));
}); Defensive patterns
Strategy: type-guard
Validate before calling
static boolean isConvertibleToMessage(MessageDTO d) {
return d instanceof ToolRequestMessageDTO || d instanceof AssistantMessageDTO || d instanceof UserMessageDTO || d instanceof ToolResponseMessageDTO;
} Type guard
static Message safeToMessage(MessageDTO d) {
if (isConvertibleToMessage(d)) return MessageDTO.MessageDTOFactory.toMessage(d);
return null; // e.g. ToolRequestConfirmMessageDTO has no reverse mapping
} Try / catch
try {
Message m = MessageDTO.MessageDTOFactory.toMessage(dto);
} catch (IllegalArgumentException e) {
log.warn("Skipping non-reversible DTO: {}", e.getMessage());
} Prevention
- Skip ToolRequestConfirmMessageDTO entries when rebuilding Messages from DTO maps.
- Never put human-in-the-loop confirm DTOs into maps that will be round-tripped to Messages.
- Keep custom MessageDTO implementations out of state converted via the factory.
When it happens
Trigger: Calling MessageDTOFactory.toMessage(dto) with a ToolRequestConfirmMessageDTO (e.g., DTOs deserialized from an interruption/pending-confirm payload), or with any custom MessageDTO implementation, then attempting to rebuild Spring AI Messages from the full DTO set (round-tripping thread values back into graph state).
Common situations: Persisting thread state as DTOs and later converting every DTO back to Messages when resuming a graph; human-in-the-loop flows that stored a tool-confirm DTO in the same map as normal messages; custom MessageDTO subclasses added by application code without updating the factory.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unsupported message type:
- extra tool param should be map
- INVALID_PARAMS
- user define param: + userParamParam.getField() + is empty
- failed to create dir: + saveFile.getParentFile()
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/f986b59a78ebbfbd.
Report an issue: GitHub.