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

  1. Construct options with ToolCallingChatOptions.builder() so the instanceof branch succeeds and your settings are copied with tool callbacks merged.
  2. If you need provider-specific options, ensure the class still implements ToolCallingChatOptions (most Spring AI provider options do).
  3. After construction, assert options instanceof ToolCallingChatOptions in your own setup code to catch regressions early.
  4. 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

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


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/aa4aca7efc2496e9. Report an issue: GitHub.