alibaba/spring-ai-alibaba · error · IllegalStateException

Tool definition is null

Error message

Tool definition is null

What it means

Thrown by NacosMcpGatewayToolCallback.call when its internal toolDefinition field is null at invocation time, an IllegalStateException signaling the callback was not properly initialized. Call cannot proceed to dispatch the MCP request without a tool definition (name, protocol, remote server config).

Source

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

	@Override
	public String call(@NonNull final String input) {
		return call(input, new ToolContext(Maps.newHashMap()));
	}

	@Override
	@SuppressWarnings("unchecked")
	public String call(@NonNull final String input, final ToolContext toolContext) {
		try {
			try {
				logger.info("[call] input: {} toolContext: {}", input, JacksonUtils.toJson(toolContext));
			} catch (Exception e) {
				// Ignore logging errors
			}

			// 参数验证
			if (this.toolDefinition == null) {
				throw new IllegalStateException("Tool definition is null");
			}

			// input解析
			logger.info("[call] input string: {}", input);
			Map<String, Object> args = new HashMap<>();
			if (!input.isEmpty()) {
				try {
					args = objectMapper.readValue(input, Map.class);
					logger.info("[call] parsed args: {}", args);
				}
				catch (Exception e) {
					logger.error("[call] Failed to parse input to args", e);
					// 如果解析失败,尝试作为单个参数处理
					args.put("input", input);
				}
			}

			String protocol = this.toolDefinition.getProtocol();

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Verify how the callback is constructed and ensure a non-null ToolDefinition is supplied.
  2. Check Nacos MCP registry metadata so the service exposes a complete tool definition.
  3. Fail fast at construction: reject null definitions in the constructor instead of at call time.
  4. If definitions load asynchronously, gate usage until initialization completes.

Example fix

// before
callback.call(input); // callback built with null definition
// after: guard at construction
if (toolDefinition == null) {
    throw new IllegalArgumentException("ToolDefinition must not be null when building NacosMcpGatewayToolCallback");
}
NacosMcpGatewayToolCallback callback = new NacosMcpGatewayToolCallback(toolDefinition, ...);
Defensive patterns

Strategy: type-guard

Validate before calling

boolean isCallable(NacosMcpGatewayToolCallback cb) {
    try {
        Field f = cb.getClass().getDeclaredField("toolDefinition");
        f.setAccessible(true);
        return f.get(cb) != null;
    } catch (ReflectiveOperationException e) { return false; }
}
// or expose a getter and check cb.getToolDefinition() != null before call()

Type guard

if (callback == null || callback.getToolDefinition() == null) {
    throw new IllegalStateException("Callback not initialized with a tool definition");
}

Try / catch

try {
    return callback.call(input);
} catch (IllegalStateException e) {
    if ("Tool definition is null".equals(e.getMessage())) {
        logger.error("Rebuild the callback with a valid ToolDefinition loaded from Nacos");
    }
    throw e;
}

Prevention

When it happens

Trigger: call(String input) invoked on a callback constructed without a toolDefinition — e.g. built from an incomplete/invalid Nacos MCP service descriptor, or the definition failed to load during bean construction and null was stored.

Common situations: Nacos service metadata missing the tool definition fields; building callbacks manually without passing the definition; race or ordering issue where the callback is used before definitions load.

Related errors


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