{"record":{"id":"83eeaaf2da2abc49","repo":"apache/shenyu","slug":"tool-execution-timeout-or-error-e-getmessage","errorCode":null,"errorMessage":"Tool execution timeout or error: ${e.getMessage()}","messagePattern":"Tool execution timeout or error: (.+?)","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":282,"sourceCode":"                    }\n                })\n                .subscribe();\n\n        // Wait for the response with timeout\n        try {\n            final String result = responseFuture.get(DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS);\n            LOG.debug(\"Tool call completed successfully for session: {}\", sessionId);\n            return result;\n        } catch (Exception e) {\n            LOG.error(\"Timeout or error waiting for response for session {}: {}\", sessionId, e.getMessage(), e);\n\n            // Ensure cleanup on error for temporary sessions\n            if (isTemporarySession) {\n                LOG.debug(\"Emergency cleanup of temporary session on error: {}\", sessionId);\n                ShenyuMcpExchangeHolder.remove(sessionId);\n            }\n\n            throw new RuntimeException(\"Tool execution timeout or error: \" + e.getMessage(), e);\n        }\n    }\n\n    /**\n     * Builds a decorated ServerWebExchange for tool execution.\n     * <p>Creates a new exchange with modified request (method, path, headers, body),\n     * response decorator based on protocol type, and updated Shenyu context and metadata.</p>\n     *\n     * @param originExchange the original exchange\n     * @param responseFuture the future for capturing response\n     * @param sessionId      the session identifier\n     * @param configStr      the request configuration\n     * @param input          the tool input parameters\n     * @return the decorated exchange ready for execution\n     */\n    private ServerWebExchange buildDecoratedExchange(final ServerWebExchange originExchange,\n                                                     final CompletableFuture<String> responseFuture,\n                                                     final String sessionId,","sourceCodeStart":264,"sourceCodeEnd":300,"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#L264-L300","documentation":"executeToolCall performs the decorated downstream exchange for the tool, often with a timeout guard. If execution throws or times out, it cleans up temporary MCP sessions and rethrows as RuntimeException('Tool execution timeout or error: ...'). It distinguishes the execution phase failure from earlier setup failures in call().","triggerScenarios":"The reactive tool execution inside executeToolCall times out or the downstream HTTP call errors (connection refused, 5xx, blocked selector/rule), while a valid session and config were already established.","commonSituations":"Backend service behind the gateway is down or slow; configured timeout too short for a long-running tool; wrong path in requestConfig leading to 404/500 from the gateway itself.","solutions":["Inspect the wrapped cause: TimeoutException means increase the tool execution timeout or speed up the backend; IOException means connectivity.","Verify the target service is up and the gateway route (selector/rule) matches the configured path.","Increase the MCP tool execution timeout configuration for slow backends.","Retest with a simple tool call to isolate whether the failure is tool-specific."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return callback.call(args, ctx);\n} catch (RuntimeException e) {\n    Throwable c = e.getCause();\n    if (c instanceof java.util.concurrent.TimeoutException) {\n        // raise timeout or return graceful 'tool too slow' response\n    } else if (c instanceof java.io.IOException) {\n        // backend unreachable: check service health, maybe retry\n    }\n    throw e;\n}","preventionTips":["Set MCP tool execution timeouts comfortably above backend p99 latency.","Monitor backend health; unhealthy upstreams will surface as this error.","Verify selector/rule routing matches the configured tool path before enabling a tool.","Use persistent MCP sessions to avoid cleanup-related edge cases."],"tags":["mcp","timeout","http","ai"],"backgroundTag":"request-timeout","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"}