alibaba/spring-ai-alibaba · error

LLM may have adapted the tool name

Error message

LLM may have adapted the tool name '{}', especially if the name was truncated due to length limits. If this is the case, you can customize the prefixing and processing logic using McpToolNamePrefixGenerator

What it means

During local tool gathering, DefaultBuilder resolves each requested tool name through the configured ToolCallbackResolver. When resolve() returns null for a name, it logs this warning (suspecting the LLM altered a truncated/prefixed MCP tool name) and then throws IllegalStateException.

Solutions

  1. Verify the exact registered tool name is used (log available tool names and compare)
  2. Shorten tool names or configure a McpToolNamePrefixGenerator whose output the model faithfully reproduces
  3. Ensure the ToolCallbackResolver is wired with the registry containing the tool (resolver was non-null, but resolved nothing)
  4. Check that MCP server tool naming config hasn't changed between runs

Example fix

// before
builder.tools("spring_ai_alibaba_mcp_very_long_tool_name_that_gets_truncat");
// after
builder.tools("mcp_long_tool_name"); // short registered name, within model name-length limits
Defensive patterns

Strategy: validation

Validate before calling

Set<String> registered = resolver.getClass() != null ? availableToolNames() : Set.of();
if (!registered.contains(toolName)) { throw new IllegalArgumentException("Unknown tool: " + toolName + "; available: " + registered); }

Type guard

static boolean toolExists(ToolCallbackResolver r, String name) { try { return r.resolve(name) != null; } catch (Exception e) { return false; } }

Try / catch

try { builder.tools(names); } catch (IllegalStateException e) { log.error("Tool resolution failed: {}", e.getMessage()); /* retry with corrected names or re-register tools */ }

Prevention

When it happens

Trigger: AllTools/gatherLocalTools is given a tool name that no registered ToolCallback matches — typically because the LLM emitted an LLM-mangled MCP tool name (prefix stripped/changed or truncated by name-length limits) instead of the exact registered name.

Common situations: Long MCP tool names exceeding model limits; custom McpToolNamePrefixGenerator mismatching what the model echoes back; tool registered in a different agent/registry than the one being queried.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

			}
		}
		
		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));
					if (logger.isDebugEnabled()) {
						logger.debug("Extracted {} tools from ToolCallbackResolver (ToolCallbackProvider)",
								resolverTools.length);
					}
				}

View on GitHub (pinned to f82da0b50f)