apache/pulsar · error · java.util.concurrent.CompletionException
${ex.getMessage()}
Error message
${ex.getMessage()} What it means
The async closeAsync() maps any exception from the underlying client's close future into a CompletionException wrapping a PulsarClientException built from the original message. Callers observe it as an exceptionally-completed CompletableFuture whose cause is this exception — the graceful close of the v4 client failed.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/PulsarClientV5.java:113
if (transactionTimeout != null) {
builder.withTransactionTimeout(transactionTimeout.toMillis(), TimeUnit.MILLISECONDS);
}
return builder.build().thenApply(v4Txn -> (Transaction) new TransactionV5(v4Txn));
}
@Override
public void close() throws PulsarClientException {
try {
v4Client.close();
} catch (org.apache.pulsar.client.api.PulsarClientException e) {
throw new PulsarClientException(e.getMessage(), e);
}
}
@Override
public CompletableFuture<Void> closeAsync() {
return v4Client.closeAsync().exceptionally(ex -> {
throw new CompletionException(new PulsarClientException(ex.getMessage(), ex));
});
}
@Override
public void shutdown() {
try {
v4Client.shutdown();
} catch (org.apache.pulsar.client.api.PulsarClientException e) {
throw new RuntimeException(e);
}
}
}
View on GitHub (pinned to 820761864e)
Solutions
- Handle the exceptionally-completed future: inspect the wrapped PulsarClientException cause for the root failure
- Retry closeAsync if the failure was transient (network), or fall back to shutdown() for forceful teardown
- Ensure you are not closing the same client twice concurrently
Example fix
// before
client.closeAsync(); // exception ignored or surfaces far away
// after
client.closeAsync().exceptionally(ex -> {
log.warn("Client close failed", ex);
return null;
}); Defensive patterns
Strategy: try-catch
Try / catch
client.closeAsync().whenComplete((v, ex) -> {
if (ex != null) log.warn("Async close failed: {}", ex.getMessage(), ex.getCause());
}); Prevention
- Always attach whenComplete/exceptionally to closeAsync futures
- Coordinate close and shutdown so neither runs twice
- Expect transient network failures during close and retry once if needed
When it happens
Trigger: CompletableFuture returned by PulsarClientV5.closeAsync() completes exceptionally when the wrapped client's closeAsync fails: broker unreachable during producer/consumer teardown, or the client is already closed.
Common situations: Closing clients during a network outage; shutdown sequences where closeAsync is chained and the wrapped cause surfaces in logs; tests tearing down clients after brokers were stopped.
Related errors
- ${e.getMessage()}
- ${cause}
- ${cause}
- (wraps underlying failure cause)
- ManagedLedgerFactory is already closed.
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/ab69f1598c0aae1b.
Report an issue: GitHub.