apache/shenyu · error · RuntimeException

Tool execution failed

Error message

Tool execution failed: ${e.getMessage()}

What it means

ShenyuToolCallback.call wraps the entire MCP tool invocation (session lookup, input parsing, config extraction, downstream HTTP execution) in a try/catch. Any exception escaping the inner execution is logged and rethrown as a RuntimeException with the prefix 'Tool execution failed:'. It is a generic barrier so MCP clients get a message instead of a raw framework stack.

Solutions

  1. Read the 'cause' of the RuntimeException and the LOG.error output — the real failure is the wrapped exception.
  2. Check the log line 'Failed to process tool call for <tool>' for tool name and root cause.
  3. Validate that the tool's requestConfig JSON in the admin MCP config is non-empty and well-formed.
  4. Verify the MCP client is sending valid JSON arguments matching the tool schema.
  5. Confirm the target backend service is reachable from the gateway.
Defensive patterns

Strategy: try-catch

Validate before calling

if (toolDefinition == null || !(toolDefinition instanceof ShenyuToolDefinition sdef)
        || !StringUtils.hasText(sdef.requestConfig())) {
    throw new IllegalArgumentException("Tool definition/config invalid before call");
}

Type guard

boolean isShenyuTool(ToolDefinition d) {
    return d instanceof ShenyuToolDefinition;
}

Try / catch

try {
    return callback.call(args, toolContext);
} catch (RuntimeException e) {
    Throwable root = e.getCause() != null ? e.getCause() : e;
    log.error("MCP tool '{}' failed: {}", toolName, root.getMessage(), root);
    return "Tool temporarily unavailable, please retry later";
}

Prevention

When it happens

Trigger: Any exception during call(): invalid ShenyuToolDefinition, empty request config, malformed input JSON, tool execution timeout, or downstream request failure inside executeToolCall.

Common situations: MCP client sends malformed JSON arguments; downstream service unreachable; session exchange missing from the holder; tool config in admin dashboard missing requestConfig.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/c5af4c37ece45341. 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:160

            // Extract MCP session context (must be pre-established)
            final McpSyncServerExchange mcpExchange = extractMcpExchange(toolContext);
            final String sessionId = extractSessionId(mcpExchange);

            // Validate and extract tool configuration
            final ShenyuToolDefinition shenyuTool = validateToolDefinition();
            final String configStr = extractRequestConfig(shenyuTool);

            // Get pre-stored exchange and plugin chain
            final ServerWebExchange originExchange = getOriginExchange(sessionId);
            final ShenyuPluginChain chain = getPluginChain(originExchange);

            // 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;
    }

    /**

View on GitHub (pinned to 567142e072)