alibaba/spring-ai-alibaba · error · IllegalStateException

ToolCallbackResolver is null; cannot resolve tool name:

Error message

ToolCallbackResolver is null; cannot resolve tool name: 

What it means

DefaultBuilder.gatherLocalTools (reached via allTools) resolves tools registered only by name through the configured ToolCallbackResolver. If the resolver reference is null it throws IllegalStateException, since tool names cannot be turned into ToolCallback instances without it.

Solutions

  1. Set the resolver on the builder: .toolCallbackResolver(resolver) (e.g. the Spring ToolCallbackResolver bean).
  2. Register the tools as ToolCallback/MethodToolCallback objects instead of bare names.
  3. Ensure the Spring context is fully started so the resolver bean is available before building the agent.

Example fix

// before
ReactAgent.builder().name("a").model(model).tools("getTime").build();
// after
ReactAgent.builder().name("a").model(model).tools("getTime").toolCallbackResolver(resolver).build();
Defensive patterns

Strategy: type-guard

Validate before calling

if (resolver == null && !Collections.disjoint(toolNames, toolNames)) throw new IllegalStateException("Tool names registered but no ToolCallbackResolver set");

Type guard

boolean canResolveByName(ToolCallbackResolver r, List<String> names) { return r != null || names == null || names.isEmpty(); }

Try / catch

try { agent = builder.build(); } catch (IllegalStateException e) { if (e.getMessage().startsWith("ToolCallbackResolver is null")) { throw new IllegalStateException("Set .toolCallbackResolver(...) when registering tools by name", e); } throw e; }

Prevention

When it happens

Trigger: Building a ReactAgent where tools were supplied as String tool names (e.g. .tools("myTool")) but no ToolCallbackResolver was set on the builder.

Common situations: Using tool-name registration in a plain application without Spring's tool resolution wiring; forgetting .toolCallbackResolver(...) on the builder; constructing DefaultBuilder manually outside Spring context.

Related errors


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

Appendix: source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/DefaultBuilder.java:258

		}
		
		if (CollectionUtils.isNotEmpty(toolCallbackProviders)) {
			for (var provider : toolCallbackProviders) {
				regularTools.addAll(List.of(provider.getToolCallbacks()));
			}
		}
		
		if (CollectionUtils.isNotEmpty(toolNames)) {
			for (String toolName : toolNames) {
				// Skip the tool if it is already present in the request toolCallbacks.
				// That might happen if a tool is defined in the options
				// both as a ToolCallback and as a tool name.
				if (regularTools.stream().anyMatch(tool -> tool.getToolDefinition().name().equals(toolName))) {
					continue;
				}
				
				if (this.resolver == null) {
					throw new IllegalStateException(
							"ToolCallbackResolver is null; cannot resolve tool name: " + toolName);
				}
				ToolCallback toolCallback = this.resolver.resolve(toolName);
				if (toolCallback == null) {
					logger.warn(POSSIBLE_LLM_TOOL_NAME_CHANGE_WARNING, toolName);
					throw new IllegalStateException("No ToolCallback found for tool name: " + toolName);
				}
				regularTools.add(toolCallback);
			}
		}
		
		// If regularTools is empty and resolver is provided, try to extract tools from resolver
		if (regularTools.isEmpty() && this.resolver != null) {
			// Check if resolver also implements ToolCallbackProvider
			if (this.resolver instanceof ToolCallbackProvider provider) {
				ToolCallback[] resolverTools = provider.getToolCallbacks();
				if (resolverTools != null && resolverTools.length > 0) {
					regularTools.addAll(List.of(resolverTools));

View on GitHub (pinned to f82da0b50f)