alibaba/arthas · error · TimeoutException
Timeout waiting for response to request {} for task {}
Error message
Timeout waiting for response to request {} for task {} What it means
InMemoryTaskMessageQueue.waitForResponse polls a per-task response queue (polling on an interval) for a specific requestId. If no matching Response object lands in responseQueues[taskId] before the deadline elapses, the CompletableFuture completes exceptionally with a CompletionException wrapping a TimeoutException. This is the MCP server's mechanism for correlating an asynchronous tool request with its reply from the task consumer thread.
Source
Thrown at arthas-mcp-server/src/main/java/com/taobao/arthas/mcp/server/task/InMemoryTaskMessageQueue.java:116
if (requestId.equals(response.requestId())) {
queue.remove(response);
logger.debug("waitForResponse: Found response for request {} in task {}",
requestId, taskId);
return response;
}
}
}
try {
Thread.sleep(pollInterval);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new CompletionException("Interrupted while waiting for response", e);
}
}
logger.warn("waitForResponse: Timeout waiting for response to request {} for task {}",
requestId, taskId);
throw new CompletionException(new TimeoutException(
"Timeout waiting for response to request " + requestId + " for task " + taskId));
});
}
@Override
public CompletableFuture<Void> clearTask(String taskId) {
return CompletableFuture.runAsync(() -> {
ConcurrentLinkedQueue<QueuedMessage> actionableQueue = actionableQueues.remove(taskId);
ConcurrentLinkedQueue<QueuedMessage.Response> responseQueue = responseQueues.remove(taskId);
int totalCleared = 0;
if (actionableQueue != null) totalCleared += actionableQueue.size();
if (responseQueue != null) totalCleared += responseQueue.size();
if (totalCleared > 0) {
logger.debug("Cleared {} messages for task {}", totalCleared, taskId);
}
});
}
View on GitHub (pinned to 21cf2e9ba5)
Solutions
- Verify the task consumer is still alive and draining the actionable queue for that taskId.
- Increase the timeout passed to waitForResponse for long-running operations (heap dump, profiler).
- Ensure no concurrent clearTask(taskId) is cancelling the task while a response is pending.
- Check that the response is enqueued with the exact same requestId used in the request (correlation key match).
- If the target process is genuinely unresponsive, restart the Arthas session and reissue the request.
Example fix
// before queue.waitForResponse(reqId, taskId, Duration.ofSeconds(5)); // after - size the timeout to the operation's real cost long secs = isHeavyOp ? 120 : 5; queue.waitForResponse(reqId, taskId, Duration.ofSeconds(secs));
Defensive patterns
Strategy: try-catch
Validate before calling
long deadline = System.nanoTime() + timeout.toNanos();
if (!queue.hasLiveConsumer(taskId)) {
// consumer missing; do not bother waiting
return;
} Try / catch
try {
queue.waitForResponse(reqId, taskId, timeout).join();
} catch (CompletionException ce) {
if (ce.getCause() instanceof TimeoutException) {
logger.warn("response timeout for task {} req {}", taskId, reqId);
// optionally retry once or fall back
} else {
throw ce;
}
} Prevention
- Size the timeout to the real cost of the operation (heap dumps/profiling need minutes).
- Avoid calling clearTask while a waitForResponse is outstanding for that taskId.
- Log requestId correlation at enqueue and dequeue to catch mismatches early.
- Health-check the task consumer thread and restart dead consumers.
When it happens
Trigger: Calling waitForResponse(requestId, taskId, timeout) when the task's consumer thread is not draining actionableQueues[taskId], when the producer enqueues a Response under a different requestId, when clearTask(taskId) ran and removed responseQueues[taskId] mid-wait, or when the target task simply never produces a reply within the configured timeout.
Common situations: Target JVM/Arthas session is busy or hung and cannot service the request; the MCP transport disconnects after the request but before the response; requestId correlation is broken by a buggy tool implementation; the configured timeout is too short for a heavy operation (e.g. heap dump, large trace); a race where clearTask is invoked concurrently with an outstanding request.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- -32603
- Tool with name '${toolName}' already exists
- Tool with name '${toolName}' not found
- Resource with URI '${resourceUri}' already exists
- Resource with URI '${resourceUri}' not found
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/ed38d2c356921616.
Report an issue: GitHub.