apache/pulsar · error · org.apache.pulsar.client.impl.v5.PulsarClientException

Close interrupted

Error message

Close interrupted

What it means

Thrown by MultiTopicQueueConsumer.close() when the thread waiting on closeAsync().get() is interrupted. The method restores the interrupt flag before throwing, so the caller's interruption status is preserved. Close did not complete.

Source

Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/MultiTopicQueueConsumer.java:360

            log.debug().attr("topic", parent)
                    .log("Ack for removed topic; dropping");
            return;
        }
        action.accept(state.consumer);
    }

    @Override
    public AsyncQueueConsumer<T> async() {
        return asyncView;
    }

    @Override
    public void close() throws PulsarClientException {
        try {
            closeAsync().get();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new PulsarClientException("Close interrupted", e);
        } catch (ExecutionException e) {
            throw new PulsarClientException(e.getCause());
        }
    }

    @Override
    public CompletableFuture<Message<T>> receiveAsync() {
        return mux.receiveAsync();
    }

    @Override
    public CompletableFuture<Void> closeAsync() {
        if (closed) {
            return CompletableFuture.completedFuture(null);
        }
        closed = true;
        watcher.close();
        mux.close();

View on GitHub (pinned to 820761864e)

Solutions

  1. Handle PulsarClientException in the close path and re-check Thread.interrupted()
  2. Prefer closeAsync() and attach callbacks instead of blocking get() in interruptible threads
  3. Delay executor shutdownNow() until after consumer close completes

Example fix

// before
consumer.close(); // called on an interruptible executor thread
// after
try {
    consumer.closeAsync().get(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt(); // preserve flag, handle shutdown
}
Defensive patterns

Strategy: try-catch

Try / catch

try { consumer.close(); } catch (PulsarClientException e) { if (Thread.interrupted()) { /* shutdown in progress */ } }

Prevention

When it happens

Trigger: A shutdown hook, executor shutdown, or Future cancellation interrupts the thread while it blocks in close().

Common situations: Application shutdown where an executor's shutdownNow() interrupts worker threads holding consumers; timeouts that cancel/interrupt the closing thread.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/87dc539088004107. Report an issue: GitHub.