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

  1. Verify the task consumer is still alive and draining the actionable queue for that taskId.
  2. Increase the timeout passed to waitForResponse for long-running operations (heap dump, profiler).
  3. Ensure no concurrent clearTask(taskId) is cancelling the task while a response is pending.
  4. Check that the response is enqueued with the exact same requestId used in the request (correlation key match).
  5. 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

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

Related errors


AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14). Data as JSON: /api/errors/ed38d2c356921616. Report an issue: GitHub.