alibaba/spring-ai-alibaba · warning
chatOptions type ({}) should be consistent with the default
Error message
chatOptions type ({}) should be consistent with the default options type ({}) from ChatModel/ChatClient for proper merging. What it means
When merging runtime chatOptions with the agent's default options, DefaultBuilder warns if the runtime options class differs from the source (ChatModel/ChatClient default) options class, because ModelOptionsUtils.merge relies on both being the same concrete type for proper merging; the merge still proceeds via reflection but may drop options.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/DefaultBuilder.java:355
}
/**
* Merge source options (from ChatModel or ChatClient) with agent-level chatOptions.
* Agent-level options take precedence. Uses ModelOptionsUtils.merge with the source
* options type as the target.
*/
@SuppressWarnings("unchecked")
private static ChatOptions mergeSourceOptionsWithAgentOptions(ChatOptions sourceOptions,
ChatOptions agentOptions) {
if (sourceOptions == null) {
return agentOptions;
}
if (agentOptions == null) {
return sourceOptions;
}
Class<?> sourceOptionsClass = sourceOptions.getClass();
if (sourceOptionsClass == agentOptions.getClass()) {
logger.warn(
"chatOptions type ({}) should be consistent with the default options type ({}) from ChatModel/ChatClient for proper merging.",
agentOptions.getClass().getName(), sourceOptionsClass.getName());
}
// Class<ChatOptions> targetClass = (Class<ChatOptions>) sourceOptionsClass;
// ChatOptions agentAsSourceType = ModelOptionsUtils.copyToTarget(agentOptions, ChatOptions.class, targetClass);
return (ChatOptions) ModelOptionsUtils.merge(agentOptions, sourceOptions, sourceOptionsClass);
}
/**
* Get the default ChatOptions from a ChatModel via reflection (e.g. {@code getDefaultOptions()}).
* @param model the ChatModel instance (may be null)
* @return the model's default options, or null if not set or reflection fails
*/
private static ChatOptions getChatModelDefaultOptions(ChatModel model) {
if (model == null) {
return null;
}
try {View on GitHub (pinned to f82da0b50f)
Solutions
- Pass runtime options of the same concrete class as the model's default options
- Change the underlying ChatModel/ChatClient so its default options type matches the options you supply
- Use ModelOptionsUtils.copyToTarget to convert the runtime options to the default options class before the call
- Remove the mismatched per-request options and configure everything on the model defaults
Example fix
// before ChatOptions opts = new OpenAiChatOptions(); // model defaults are DashScopeChatOptions agent.call(options -> opts); // after DashScopeChatOptions opts = DashScopeChatOptions.builder().build(); // same type as model defaults agent.call(options -> opts);
Defensive patterns
Strategy: type-guard
Validate before calling
if (runtimeOptions != null && defaultOptions != null && runtimeOptions.getClass() != defaultOptions.getClass()) { log.warn("Options type mismatch: {} vs {}", runtimeOptions.getClass(), defaultOptions.getClass()); } Type guard
static boolean sameOptionsType(ChatOptions a, ChatOptions b) { return a == null || b == null || a.getClass() == b.getClass(); } Prevention
- Always build per-request options with the provider-specific class matching the configured ChatModel
- Avoid mixing providers' ChatOptions implementations in one application without conversion
- Add an assertion/test that agent options class equals model default options class
When it happens
Trigger: effectiveOptions is called with a runtime ChatOptions subclass (e.g. DashScopeChatOptions) different from the model's default options class (e.g. OpenAiChatOptions), so agentOptions.getClass() != sourceOptions.getClass().
Common situations: Mixing model providers: agent configured for DashScope defaults but request passes OpenAI-style options; passing generic ChatOptions where provider-specific options are the default; multiple ChatModels on the classpath picking a different default.
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
- copy() method did not return a ChatOptions instance
- The provided chatOptions is not of type ToolCallingChatOptio
- unknown component type: + componentType.getValue()
- extra tool param should be map
- INVALID_PARAMS
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/f080260708686efc.
Report an issue: GitHub.