apache/shenyu · error · IllegalStateException
Tool definition must be of type ShenyuToolDefinition, got
Error message
Tool definition must be of type ShenyuToolDefinition, got: ${toolDefinition.getClass().getSimpleName()} What it means
ShenyuToolCallback requires its ToolDefinition to be a ShenyuToolDefinition (the ShenYu-specific subtype exposing requestConfig). validateToolDefinition throws IllegalStateException if the injected definition is a plain or foreign ToolDefinition implementation, because the request-config extraction would otherwise fail.
Solutions
- Create tool specs using ShenyuToolDefinition (its builder) so the definition passed to ShenyuToolCallback is the right type.
- Check how the tool specification is registered and ensure no adapter converts it to a base ToolDefinition.
- After dependency upgrades, confirm the MCP integration still constructs ShenyuToolDefinition instances.
Example fix
// before
ToolDefinition def = ToolDefinition.builder().name("t").build();
// after
ShenyuToolDefinition def = ShenyuToolDefinition.builder().name("t").requestConfig(configJson).build(); Defensive patterns
Strategy: type-guard
Type guard
ShenyuToolDefinition asShenyuToolDefinition(ToolDefinition d) {
if (d instanceof ShenyuToolDefinition s) {
return s;
}
throw new IllegalArgumentException("Expected ShenyuToolDefinition, got " + d.getClass().getName());
} Try / catch
try {
return callback.call(args, ctx);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Tool definition must be")) {
// rebuild tool spec with ShenyuToolDefinition and retry registration
}
throw e;
} Prevention
- Always register MCP tools via the Shenyu builder that produces ShenyuToolDefinition.
- Add an assertion at tool-registration time: assert definition instanceof ShenyuToolDefinition.
- Re-run tool registration tests after upgrading Spring AI / MCP SDK versions.
- Avoid ad-hoc ToolDefinition adapters in registration code.
When it happens
Trigger: Constructing ShenyuToolCallback with a McpServerFeature.SyncToolSpecification or Spring AI ToolDefinition that is not an instance of ShenyuToolDefinition — typically when a tool is registered by code that builds a generic ToolDefinition instead of ShenyuToolDefinition.
Common situations: Registering MCP tools programmatically with a hand-rolled ToolDefinition; upgrading Spring AI/MCP SDK so the callback receives a differently-typed definition; forgetting to wrap the spec via the Shenyu builder.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Tool execution failed
- Request configuration cannot be empty
- Tool execution timeout or error
- Invalid input JSON format
- Invalid JSON format
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/26546ac536462d05.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java:172
// Execute the tool call through the plugin chain
return executeToolCall(originExchange, chain, sessionId, configStr, input);
} catch (Exception e) {
LOG.error("Failed to process tool call for '{}': {}", toolDefinition.name(), e.getMessage(), e);
throw new RuntimeException("Tool execution failed: " + e.getMessage(), e);
}
}
/**
* Validates and casts the tool definition to Shenyu-specific type.
*
* @return the Shenyu tool definition
* @throws IllegalStateException if tool definition is not of expected type
*/
private ShenyuToolDefinition validateToolDefinition() {
if (!(this.toolDefinition instanceof ShenyuToolDefinition)) {
throw new IllegalStateException("Tool definition must be of type ShenyuToolDefinition, got: "
+ this.toolDefinition.getClass().getSimpleName());
}
return (ShenyuToolDefinition) this.toolDefinition;
}
/**
* Extracts and validates the request configuration from the tool definition.
*
* @param definition the Shenyu tool definition
* @return the request configuration string
* @throws IllegalStateException if configuration is missing or invalid
*/
private String extractRequestConfig(final ShenyuToolDefinition definition) {
final String config = definition.requestConfig();
if (!StringUtils.hasText(config)) {
throw new IllegalStateException("Request configuration cannot be empty");
}
LOG.debug("Using request configuration with length: {} chars", config.length());View on GitHub (pinned to 567142e072)