alibaba/arthas · error · McpError
-32603
-32603
Error message
Task did not complete within timeout
What it means
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.
Source
Thrown at arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/task/DefaultTaskManager.java:464
.message("Task did not complete within timeout")
.data("Task ID: " + taskId)
.build());
return failed;
}
McpSchema.Task terminalTask = updates.get(updates.size() - 1);
if (!terminalTask.isTerminal()) {
CompletableFuture<McpSchema.Result> failed = new CompletableFuture<>();
failed.completeExceptionally(McpError.builder(McpSchema.ErrorCodes.INTERNAL_ERROR)
.message("Task did not complete within timeout")
.data("Task ID: " + taskId)
.build());
return failed;
}
return fetchTaskResult(taskId, sessionId);
})
.exceptionally(ex -> {
if (ex instanceof TimeoutException || ex.getCause() instanceof TimeoutException) {
throw new RuntimeException(
McpError.builder(McpSchema.ErrorCodes.INTERNAL_ERROR)
.message("Task did not complete within timeout")
.data("Task ID: " + taskId)
.build());
}
throw new RuntimeException(ex);
});
}
/**
* Processes all queued side-channel messages for an INPUT_REQUIRED task, then waits for terminal state.
*/
private CompletableFuture<McpSchema.Result> processQueuedMessagesAndWaitForTerminal(
TaskManagerHost.TaskHandlerContext ctx, String taskId, String sessionId) {
logger.debug("processQueuedMessagesAndWaitForTerminal: Starting side-channel processing for task {}", taskId);
return processAllQueuedMessages(ctx, taskId)
.thenCompose(v -> {View on GitHub (pinned to 21cf2e9ba5)
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.
Example fix
// before
return taskTool.createTaskHandler().createTask(args, extra); // may hang
// after
Future<McpSchema.Result> f = taskTool.createTaskHandler().createTask(args, extra);
try {
return f.get(extendedTimeout, TimeUnit.MILLISECONDS);
} catch (TimeoutException te) {
taskStore.requestCancellation(taskId, sessionId);
throw te;
} Defensive patterns
Strategy: retry
Validate before calling
// Size the wait budget to the task's worst case before invoking long budget = Math.max(configuredTimeout, expectedMaxMillis * 2); // then poll/wait with that budget
Try / catch
try {
future.get(budget, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
Throwable c = e.getCause();
if (c instanceof McpError me && me.getMessage().contains("timeout")) {
// retry once with a larger budget, or request cancellation
taskStore.requestCancellation(taskId, sessionId);
}
throw e;
} catch (TimeoutException te) {
taskStore.requestCancellation(taskId, sessionId);
throw te;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/32f9aa40db727992.
Report an issue: GitHub.