{"record":{"id":"38771229b71daddb","repo":"apache/pulsar","slug":"close-interrupted-387712","errorCode":null,"errorMessage":"Close interrupted","messagePattern":"Close interrupted","errorType":"exception","errorClass":"PulsarClientException","httpStatus":null,"severity":"error","filePath":"pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/ScalableTopicProducer.java","lineNumber":179,"sourceCode":"            if (future.isDone() && !future.isCompletedExceptionally()) {\n                max = Math.max(max, future.join().getLastSequenceId());\n            }\n        }\n        return max;\n    }\n\n    @Override\n    public AsyncProducer<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            Throwable cause = e.getCause();\n            if (cause instanceof PulsarClientException pce) {\n                throw pce;\n            }\n            throw new PulsarClientException(cause);\n        }\n    }\n\n    /**\n     * Send a message synchronously with routing. Called by MessageBuilderV5.\n     * Returns a MessageIdV5 that includes the segment ID for ack routing.\n     */\n    MessageIdV5 sendInternal(\n            String key, T value, java.util.Map<String, String> properties,\n            java.time.Instant eventTime, Long sequenceId,\n            java.time.Duration deliverAfter, java.time.Instant deliverAt,\n            java.util.List<String> replicationClusters,","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/ScalableTopicProducer.java#L161-L197","documentation":"ScalableTopicProducer.close() blocks on closeAsync().get(); if the waiting thread is interrupted, it restores the interrupt flag and throws a generic PulsarClientException with this message. It signals that producer close did not complete because the caller's thread was interrupted, not because of a broker problem.","triggerScenarios":"Calling close() (directly or via try-with-resources) on a ScalableTopicProducer while another thread interrupts the calling thread, e.g. during shutdown, executor termination, or task timeout.","commonSituations":"Application shutdown interrupting worker threads mid-close; Future/timeout cancellation; a thread-pool executor calling close() and being shut down with shutdownNow(); publisher loops cancelled in tests.","solutions":["Avoid interrupting threads that are closing producers; use graceful shutdown (shutdown() + awaitTermination) before interrupting.","Check the interrupt source: the interrupt flag is re-set on the thread, so inspect Thread.interrupted() handling in the surrounding code.","If interruption is expected (e.g. timeouts), catch PulsarClientException and treat close as best-effort, or prefer closeAsync() with orTimeout for time-bounded shutdown.","Ensure close() is only called once per producer from a dedicated lifecycle thread."],"exampleFix":"// before\nproducer.close(); // interrupted during shutdown\n// after\nCompletableFuture<Void> f = producer.closeAsync();\ntry {\n    f.get(30, TimeUnit.SECONDS);\n} catch (TimeoutException te) {\n    f.cancel(true);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    producer.close();\n} catch (PulsarClientException e) {\n    if (e.getCause() instanceof InterruptedException) {\n        Thread.currentThread().interrupt(); // already re-set, proceed with shutdown\n    } else { throw e; }\n}","preventionTips":["Close producers on a dedicated lifecycle thread not subject to interrupts","Use closeAsync().get(timeout) instead of close() for time-bounded shutdown","Use executor.shutdown() + awaitTermination before shutdownNow()"],"tags":["interruption","lifecycle","pulsar-client"],"backgroundTag":"thread-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"}