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
- Fix the tool name in Nacos / the source that generates 'serverName_tools_toolName' so the toolName segment is non-empty.
- Trim the input and validate before concatenation: reject empty tool names when building the definition.
- 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
- Validate toolName is non-blank before concatenating 'serverName_tools_' + toolName
- Trim whitespace from names pulled from Nacos metadata
- Add a unit test for the name-extraction logic with edge cases
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
- Tool definition is null
- Protocol is null
- Remote server config is null
- No available endpoint found for service: <serviceName>
- Tool definition name is not available
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/c5b2e181631207f3.
Report an issue: GitHub.