{"record":{"id":"87dc539088004107","repo":"apache/pulsar","slug":"close-interrupted","errorCode":null,"errorMessage":"Close interrupted","messagePattern":"Close interrupted","errorType":"exception","errorClass":"org.apache.pulsar.client.impl.v5.PulsarClientException","httpStatus":null,"severity":"error","filePath":"pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/MultiTopicQueueConsumer.java","lineNumber":360,"sourceCode":"            log.debug().attr(\"topic\", parent)\n                    .log(\"Ack for removed topic; dropping\");\n            return;\n        }\n        action.accept(state.consumer);\n    }\n\n    @Override\n    public AsyncQueueConsumer<T> async() {\n        return asyncView;\n    }\n\n    @Override\n    public void close() throws PulsarClientException {\n        try {\n            closeAsync().get();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw new PulsarClientException(\"Close interrupted\", e);\n        } catch (ExecutionException e) {\n            throw new PulsarClientException(e.getCause());\n        }\n    }\n\n    @Override\n    public CompletableFuture<Message<T>> receiveAsync() {\n        return mux.receiveAsync();\n    }\n\n    @Override\n    public CompletableFuture<Void> closeAsync() {\n        if (closed) {\n            return CompletableFuture.completedFuture(null);\n        }\n        closed = true;\n        watcher.close();\n        mux.close();","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/MultiTopicQueueConsumer.java#L342-L378","documentation":"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.","triggerScenarios":"A shutdown hook, executor shutdown, or Future cancellation interrupts the thread while it blocks in close().","commonSituations":"Application shutdown where an executor's shutdownNow() interrupts worker threads holding consumers; timeouts that cancel/interrupt the closing thread.","solutions":["Handle PulsarClientException in the close path and re-check Thread.interrupted()","Prefer closeAsync() and attach callbacks instead of blocking get() in interruptible threads","Delay executor shutdownNow() until after consumer close completes"],"exampleFix":"// before\nconsumer.close(); // called on an interruptible executor thread\n// after\ntry {\n    consumer.closeAsync().get(30, TimeUnit.SECONDS);\n} catch (InterruptedException e) {\n    Thread.currentThread().interrupt(); // preserve flag, handle shutdown\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { consumer.close(); } catch (PulsarClientException e) { if (Thread.interrupted()) { /* shutdown in progress */ } }","preventionTips":["Use closeAsync() in interruptible threads","Order shutdown: close consumers before executor shutdownNow()"],"tags":["pulsar","client","close","interrupt"],"backgroundTag":"close-interrupted","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}