alibaba/spring-ai-alibaba · warning
The provided chatOptions is not of type ToolCallingChatOptio
Error message
The provided chatOptions is not of type ToolCallingChatOptions (actual type: {}). It will not take effect. Creating a new ToolCallingChatOptions with toolCallbacks instead. What it means
AgentLlmNode.buildChatOptions expects chatOptions to implement ToolCallingChatOptions so tool callbacks can be attached and internal tool execution disabled. When a ChatOptions instance of another type is supplied, the node logs this warning and builds a fresh ToolCallingChatOptions with the tool callbacks — meaning any custom settings on the original options object (temperature, topP, model name, etc.) silently do NOT take effect.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/node/AgentLlmNode.java:371
if (chatOptions != null) {
if (chatOptions instanceof ToolCallingChatOptions builderToolCallingOptions) {
ToolCallingChatOptions copiedOptions = builderToolCallingOptions.copy();
List<ToolCallback> mergedToolCallbacks = new ArrayList<>(toolCallbacks);
// Add callbacks from chatOptions that are not already present (toolCallbacks takes precedence)
for (ToolCallback callback : builderToolCallingOptions.getToolCallbacks()) {
boolean exists = mergedToolCallbacks.stream()
.anyMatch(tc -> tc.getToolDefinition().name().equals(callback.getToolDefinition().name()));
if (!exists) {
mergedToolCallbacks.add(callback);
}
}
copiedOptions.setToolCallbacks(mergedToolCallbacks);
copiedOptions.setInternalToolExecutionEnabled(false);
return copiedOptions;
} else {
logger.warn("The provided chatOptions is not of type ToolCallingChatOptions (actual type: {}). " +
"It will not take effect. Creating a new ToolCallingChatOptions with toolCallbacks instead.",
chatOptions.getClass().getName());
}
}
return ToolCallingChatOptions.builder()
.toolCallbacks(toolCallbacks)
.internalToolExecutionEnabled(false)
.build();
}
private String renderPromptTemplate(String prompt, Map<String, Object> params) {
PromptTemplate.Builder builder = PromptTemplate.builder().template(prompt);
if (templateRenderer != null) {
builder.renderer(templateRenderer);
}
return builder.build().render(params);
}View on GitHub (pinned to f82da0b50f)
Solutions
- Construct options with ToolCallingChatOptions.builder() so the instanceof branch succeeds and your settings are copied with tool callbacks merged.
- If you need provider-specific options, ensure the class still implements ToolCallingChatOptions (most Spring AI provider options do).
- After construction, assert options instanceof ToolCallingChatOptions in your own setup code to catch regressions early.
- If you must keep the foreign options object, manually transfer its fields (temperature, model, etc.) onto the ToolCallingChatOptions the node creates.
Example fix
// before
ChatOptions options = ChatOptions.builder().model("qwen-max").build();
// after
ToolCallingChatOptions options = ToolCallingChatOptions.builder()
.model("qwen-max")
.toolCallbacks(myCallbacks)
.internalToolExecutionEnabled(false)
.build(); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(chatOptions instanceof ToolCallingChatOptions)) {
throw new IllegalArgumentException("chatOptions must be ToolCallingChatOptions, got: " + chatOptions.getClass().getName());
} Type guard
static ToolCallingChatOptions asToolCalling(ChatOptions options) {
return options instanceof ToolCallingChatOptions tco ? tco
: ToolCallingChatOptions.builder().model(options.getModel()).temperature(options.getTemperature()).build();
} Prevention
- Build options with ToolCallingChatOptions.builder(), never plain ChatOptions.builder()
- Assert the instanceof in your own agent-setup code
- Re-check provider options classes after Spring AI version upgrades
- Copy custom fields manually when bridging foreign options objects
When it happens
Trigger: Passing a ChatOptions implementation that does not implement ToolCallingChatOptions into AgentLlmNode (e.g. a provider-specific options class like OpenAiChatOptions from a version that isn't a ToolCallingChatOptions, or a plain ChatOptions built via ChatOptions.builder()).
Common situations: 1) Building options with ChatOptions.builder() instead of ToolCallingChatOptions.builder(). 2) A custom ChatOptions subclass missing the ToolCallingChatOptions interface. 3) Upgrading Spring AI and swapping to a different provider's options class that lost the interface. 4) Copying options into your own type before handing them to the node.
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
- checkpoints.numRetained must be a number or numeric string,
- copy() method did not return a ChatOptions instance
- chatOptions type ({}) should be consistent with the default
- unknown component type: + componentType.getValue()
- extra tool param should be map
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/aa4aca7efc2496e9.
Report an issue: GitHub.