{"record":{"id":"c5af4c37ece45341","repo":"apache/shenyu","slug":"tool-execution-failed-e-getmessage","errorCode":null,"errorMessage":"Tool execution failed: ${e.getMessage()}","messagePattern":"Tool execution failed: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java","lineNumber":160,"sourceCode":"            // Extract MCP session context (must be pre-established)\n            final McpSyncServerExchange mcpExchange = extractMcpExchange(toolContext);\n            final String sessionId = extractSessionId(mcpExchange);\n\n            // Validate and extract tool configuration\n            final ShenyuToolDefinition shenyuTool = validateToolDefinition();\n            final String configStr = extractRequestConfig(shenyuTool);\n\n            // Get pre-stored exchange and plugin chain\n            final ServerWebExchange originExchange = getOriginExchange(sessionId);\n            final ShenyuPluginChain chain = getPluginChain(originExchange);\n\n            // Execute the tool call through the plugin chain\n            return executeToolCall(originExchange, chain, sessionId, configStr, input);\n\n        } catch (Exception e) {\n            LOG.error(\"Failed to process tool call for '{}': {}\", toolDefinition.name(), e.getMessage(), e);\n\n            throw new RuntimeException(\"Tool execution failed: \" + e.getMessage(), e);\n        }\n    }\n\n    /**\n     * Validates and casts the tool definition to Shenyu-specific type.\n     *\n     * @return the Shenyu tool definition\n     * @throws IllegalStateException if tool definition is not of expected type\n     */\n    private ShenyuToolDefinition validateToolDefinition() {\n        if (!(this.toolDefinition instanceof ShenyuToolDefinition)) {\n            throw new IllegalStateException(\"Tool definition must be of type ShenyuToolDefinition, got: \"\n                    + this.toolDefinition.getClass().getSimpleName());\n        }\n        return (ShenyuToolDefinition) this.toolDefinition;\n    }\n\n    /**","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java#L142-L178","documentation":"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.","triggerScenarios":"Any exception during call(): invalid ShenyuToolDefinition, empty request config, malformed input JSON, tool execution timeout, or downstream request failure inside executeToolCall.","commonSituations":"MCP client sends malformed JSON arguments; downstream service unreachable; session exchange missing from the holder; tool config in admin dashboard missing requestConfig.","solutions":["Read the 'cause' of the RuntimeException and the LOG.error output — the real failure is the wrapped exception.","Check the log line 'Failed to process tool call for <tool>' for tool name and root cause.","Validate that the tool's requestConfig JSON in the admin MCP config is non-empty and well-formed.","Verify the MCP client is sending valid JSON arguments matching the tool schema.","Confirm the target backend service is reachable from the gateway."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (toolDefinition == null || !(toolDefinition instanceof ShenyuToolDefinition sdef)\n        || !StringUtils.hasText(sdef.requestConfig())) {\n    throw new IllegalArgumentException(\"Tool definition/config invalid before call\");\n}","typeGuard":"boolean isShenyuTool(ToolDefinition d) {\n    return d instanceof ShenyuToolDefinition;\n}","tryCatchPattern":"try {\n    return callback.call(args, toolContext);\n} catch (RuntimeException e) {\n    Throwable root = e.getCause() != null ? e.getCause() : e;\n    log.error(\"MCP tool '{}' failed: {}\", toolName, root.getMessage(), root);\n    return \"Tool temporarily unavailable, please retry later\";\n}","preventionTips":["Always read e.getCause() — the outer message is only a wrapper.","Validate tool definitions (type + requestConfig) at registration time, not call time.","Keep gateway-to-backend health checks so downstream failures surface early.","Enable LOG.error output review for 'Failed to process tool call'."],"tags":["mcp","ai","tool-execution","wrapper-exception"],"backgroundTag":"api-request-failed","analyzedSha":"567142e07261b3e615ae8850b30f4421f455cc5d","analyzedAt":"2026-09-12T10:08:21.293Z","contentChangedAt":"2026-09-12T10:08:21.293Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}