{"record":{"id":"32f9aa40db727992","repo":"alibaba/arthas","slug":"32603","errorCode":"-32603","errorMessage":"Task did not complete within timeout","messagePattern":"Task did not complete within timeout","errorType":"error_code","errorClass":"McpError","httpStatus":null,"severity":"error","filePath":"arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/task/DefaultTaskManager.java","lineNumber":464,"sourceCode":"                                .message(\"Task did not complete within timeout\")\n                                .data(\"Task ID: \" + taskId)\n                                .build());\n                        return failed;\n                    }\n                    McpSchema.Task terminalTask = updates.get(updates.size() - 1);\n                    if (!terminalTask.isTerminal()) {\n                        CompletableFuture<McpSchema.Result> failed = new CompletableFuture<>();\n                        failed.completeExceptionally(McpError.builder(McpSchema.ErrorCodes.INTERNAL_ERROR)\n                                .message(\"Task did not complete within timeout\")\n                                .data(\"Task ID: \" + taskId)\n                                .build());\n                        return failed;\n                    }\n                    return fetchTaskResult(taskId, sessionId);\n                })\n                .exceptionally(ex -> {\n                    if (ex instanceof TimeoutException || ex.getCause() instanceof TimeoutException) {\n                        throw new RuntimeException(\n                                McpError.builder(McpSchema.ErrorCodes.INTERNAL_ERROR)\n                                        .message(\"Task did not complete within timeout\")\n                                        .data(\"Task ID: \" + taskId)\n                                        .build());\n                    }\n                    throw new RuntimeException(ex);\n                });\n    }\n\n    /**\n     * Processes all queued side-channel messages for an INPUT_REQUIRED task, then waits for terminal state.\n     */\n    private CompletableFuture<McpSchema.Result> processQueuedMessagesAndWaitForTerminal(\n            TaskManagerHost.TaskHandlerContext ctx, String taskId, String sessionId) {\n        logger.debug(\"processQueuedMessagesAndWaitForTerminal: Starting side-channel processing for task {}\", taskId);\n\n        return processAllQueuedMessages(ctx, taskId)\n                .thenCompose(v -> {","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/alibaba/arthas/blob/21cf2e9ba52b305290be7223b980ff504bb9cb5b/arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/task/DefaultTaskManager.java#L446-L482","documentation":"Thrown by DefaultTaskManager when a task does not reach a terminal state before the configured timeout elapses. It builds a McpError with ErrorCodes.INTERNAL_ERROR (-32603) and the task ID as data. It can surface in two places: when waiting on a terminal task that times out, and in the exceptionally handler when a TimeoutException is caught and rethrown as a RuntimeException wrapping the McpError.","triggerScenarios":"A long-running task-aware tool whose handler never completes within the wait/poll budget; the task's createTaskHandler blocks indefinitely; the task message queue stalls so terminal state is never reached; the polling window is shorter than the real work duration.","commonSituations":"External dependency (DB, network, subprocess) hanging; handler forgot to call a completion method; tight timeouts configured for heavy work; lost wakeups in the message queue.","solutions":["Increase the effective wait/timeout budget so it exceeds the task's realistic worst-case duration.","Ensure the task handler always reaches a terminal state (completed/failed/cancelled) even on error paths.","Make the handler cancel-aware so cancellation/interrupts propagate to the underlying work.","Add task-level heartbeats or progress updates and surface partial results instead of blocking indefinitely."],"exampleFix":"// before\nreturn taskTool.createTaskHandler().createTask(args, extra); // may hang\n\n// after\nFuture<McpSchema.Result> f = taskTool.createTaskHandler().createTask(args, extra);\ntry {\n    return f.get(extendedTimeout, TimeUnit.MILLISECONDS);\n} catch (TimeoutException te) {\n    taskStore.requestCancellation(taskId, sessionId);\n    throw te;\n}","handlingStrategy":"retry","validationCode":"// Size the wait budget to the task's worst case before invoking\nlong budget = Math.max(configuredTimeout, expectedMaxMillis * 2);\n// then poll/wait with that budget","typeGuard":null,"tryCatchPattern":"try {\n    future.get(budget, TimeUnit.MILLISECONDS);\n} catch (ExecutionException e) {\n    Throwable c = e.getCause();\n    if (c instanceof McpError me && me.getMessage().contains(\"timeout\")) {\n        // retry once with a larger budget, or request cancellation\n        taskStore.requestCancellation(taskId, sessionId);\n    }\n    throw e;\n} catch (TimeoutException te) {\n    taskStore.requestCancellation(taskId, sessionId);\n    throw te;\n}","preventionTips":["Ensure handlers always reach a terminal state, even on error paths.","Set timeouts larger than realistic worst-case runtime.","Make handlers cancel-aware so interrupts propagate.","Log handler progress to catch stuck tasks early."],"tags":["mcp","task","timeout","async","java"],"backgroundTag":null,"analyzedSha":"21cf2e9ba52b305290be7223b980ff504bb9cb5b","analyzedAt":"2026-08-14T00:57:07.243Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}