elastic/elasticsearch · error · RuntimeException

thread waiting for the response was interrupted

Error message

thread waiting for the response was interrupted

What it means

Thrown by extractAndWrapCause when the future completing a sync performRequest was cancelled/interrupted. The client re-asserts the interrupt flag (Thread.currentThread().interrupt()) and wraps the original InterruptedException in a RuntimeException so it can surface through methods that only declare checked exceptions. This is a programmer/environment signal, not a server error.

Source

Thrown at client/rest/src/main/java/org/elasticsearch/client/RestClient.java:904

        ResponseOrResponseException(Response response) {
            this.response = Objects.requireNonNull(response);
            this.responseException = null;
        }

        ResponseOrResponseException(ResponseException responseException) {
            this.responseException = Objects.requireNonNull(responseException);
            this.response = null;
        }
    }

    /**
     * Wrap the exception so the caller's signature shows up in the stack trace, taking care to copy the original type and message
     * where possible so async and sync code don't have to check different exceptions.
     */
    private static Exception extractAndWrapCause(Exception exception) {
        if (exception instanceof InterruptedException) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("thread waiting for the response was interrupted", exception);
        }
        if (exception instanceof ExecutionException) {
            ExecutionException executionException = (ExecutionException) exception;
            Throwable t = executionException.getCause() == null ? executionException : executionException.getCause();
            if (t instanceof Error) {
                throw (Error) t;
            }
            exception = (Exception) t;
        }
        if (exception instanceof ConnectTimeoutException) {
            ConnectTimeoutException e = new ConnectTimeoutException(exception.getMessage());
            e.initCause(exception);
            return e;
        }
        if (exception instanceof SocketTimeoutException) {
            SocketTimeoutException e = new SocketTimeoutException(exception.getMessage());
            e.initCause(exception);
            return e;

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure no other thread interrupts or shuts down the client/executor while a request is in flight.
  2. If you intentionally cancel, treat this RuntimeException as expected and re-check Thread.interrupted() in your handler.
  3. Avoid sharing one RestClient across threads that may close it independently.

Example fix

// before
new Thread(() -> client.performRequest(req)).start();
// later, from another thread:
client.close(); // interrupts the in-flight request
// after
// drain/await outstanding requests, then close:
client.close(); // only after no caller is mid-request
Defensive patterns

Strategy: try-catch

Try / catch

try { client.performRequest(req); }
catch (RuntimeException e) {
    if (e.getCause() instanceof InterruptedException) {
        Thread.currentThread().interrupt();
        // handle shutdown/cancellation gracefully
    } else throw e;
}

Prevention

When it happens

Trigger: The thread blocked in performRequest is interrupted (Thread.interrupt) while waiting on the async future; the RestClient is shut down while a request is in flight; the surrounding executor cancels the task.

Common situations: Calling RestClient.close() from another thread while a request is pending; shutting down an ExecutorService that wraps the client call; test timeouts interrupting the request thread.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/63445a39e0ec564d. Report an issue: GitHub.