alibaba/spring-ai-alibaba · error · RuntimeException

Extracted tool name is empty

Error message

Extracted tool name is empty

What it means

After splitting toolDefinition.name() on the '_tools_' separator, the code takes the trailing segment as the MCP tool name. If that segment is empty (name ended with the separator, e.g. 'server_tools_'), no remote tool can be addressed and a RuntimeException is thrown.

Source

Thrown at spring-boot-starters/spring-ai-alibaba-starter-config-nacos/src/main/java/com/alibaba/cloud/ai/agent/nacos/tools/NacosMcpGatewayToolCallback.java:508

				// 获取工具名称 - 从工具定义名称中提取实际的工具名称
				String toolDefinitionName = this.toolDefinition.name();
				if (toolDefinitionName == null || toolDefinitionName.isEmpty()) {
					throw new RuntimeException("Tool definition name is not available");
				}

				// 工具定义名称格式为: serverName_tools_toolName
				// 需要提取最后的 toolName 部分
				String toolName;
				if (toolDefinitionName.contains("_tools_")) {
					toolName = toolDefinitionName.substring(toolDefinitionName.lastIndexOf("_tools_") + 7);
				}
				else {
					// 如果没有 _tools_ 分隔符,使用整个名称
					toolName = toolDefinitionName;
				}

				if (toolName.isEmpty()) {
					throw new RuntimeException("Extracted tool name is empty");
				}

				// 构建传输层
				StringBuilder sseEndpoint = new StringBuilder("/sse");
				if (exportPath != null && !exportPath.isEmpty()) {
					sseEndpoint = new StringBuilder(exportPath);
					if (mcpServerVO.getQueryParams() != null) {


						if (!sseEndpoint.toString().contains("?")) {
							sseEndpoint.append("?");
						}
						Iterator<Map.Entry<String, String>> iterator = mcpServerVO.getQueryParams().entrySet()
								.iterator();
						while (iterator.hasNext()) {
							Map.Entry<String, String> next = iterator.next();
							sseEndpoint.append(next.getKey()).append("=").append(next.getValue())
									.append(iterator.hasNext() ? "&" : "");

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Fix the tool name in Nacos / the source that generates 'serverName_tools_toolName' so the toolName segment is non-empty.
  2. Trim the input and validate before concatenation: reject empty tool names when building the definition.
  3. Add an upstream check (StringUtils.isBlank) on the toolName segment before creating the callback.

Example fix

// before
String fullName = serverName + "_tools_" + toolName; // toolName may be ""
// after
if (toolName == null || toolName.isBlank()) { throw new IllegalArgumentException("toolName required"); }
String fullName = serverName + "_tools_" + toolName;
Defensive patterns

Strategy: validation

Validate before calling

int idx = toolDefinition.name().indexOf("_tools_");
if (idx < 0 || idx + "_tools_".length() >= toolDefinition.name().length()) {
    throw new IllegalArgumentException("Tool name must end with a non-empty toolName after '_tools_'");
}

Try / catch

try { return callback.call(args); }
catch (RuntimeException e) {
    if ("Extracted tool name is empty".equals(e.getMessage())) { log.error("bad tool name format: {}", toolDefinition.name()); }
    throw e;
}

Prevention

When it happens

Trigger: call() -> handleMcpStreamProtocol with a definition name like 'myServer_tools_' or '_tools_' so the extracted suffix after '_tools_' is the empty string.

Common situations: Tool names generated by concatenating 'serverName_tools_' + toolName where toolName was empty or only whitespace; truncated names from a bad sync/parsing of Nacos tool metadata; manual renames that left a dangling separator.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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