apache/pulsar · warning · PulsarClientException
Commit interrupted
Error message
Commit interrupted
What it means
TransactionV5.commit() blocks on the underlying v4 transaction's commit future. If the waiting thread is interrupted while blocked, the interrupt flag is restored and a PulsarClientException with the fixed message "Commit interrupted" is thrown. The transaction's actual commit outcome is unknown at that point — only the wait was cancelled.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/TransactionV5.java:51
private final org.apache.pulsar.client.api.transaction.Transaction v4Transaction;
private final AsyncTransaction asyncView;
TransactionV5(org.apache.pulsar.client.api.transaction.Transaction v4Transaction) {
this.v4Transaction = v4Transaction;
this.asyncView = new AsyncView();
}
org.apache.pulsar.client.api.transaction.Transaction v4Transaction() {
return v4Transaction;
}
@Override
public void commit() throws PulsarClientException {
try {
v4Transaction.commit().get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new PulsarClientException("Commit interrupted", e);
} catch (ExecutionException e) {
Throwable cause = e.getCause() != null ? e.getCause() : e;
throw new PulsarClientException(cause.getMessage(), cause);
}
}
@Override
public void abort() throws PulsarClientException {
try {
v4Transaction.abort().get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new PulsarClientException("Abort interrupted", e);
} catch (ExecutionException e) {
Throwable cause = e.getCause() != null ? e.getCause() : e;
throw new PulsarClientException(cause.getMessage(), cause);
}
}View on GitHub (pinned to 820761864e)
Solutions
- Do not interrupt threads waiting on commit(); await completion before shutdown, or use asyncView (async()) with a CompletableFuture handler instead of blocking commit().
- Check the transaction's final state after recovery — the commit may have succeeded despite the interrupt; abort/retry idempotently as needed.
- Ensure the thread's interrupt status handling is intentional: the library already restores the flag, so subsequent blocking calls will fail fast — re-create the transaction if needed.
Example fix
// before
try (TransactionV5 txn = ... ) {
txn.commit(); // blocking; interrupted on shutdown
}
// after
AsyncTransaction txn = ...;
txn.commitAsync()
.orTimeout(30, TimeUnit.SECONDS)
.whenComplete((r, ex) -> {
if (ex != null) log.warn("commit failed", ex);
}); Defensive patterns
Strategy: try-catch
Validate before calling
if (Thread.currentThread().isInterrupted()) {
throw new PulsarClientException("thread already interrupted; skipping commit");
} Try / catch
try {
txn.commit();
} catch (PulsarClientException e) {
if ("Commit interrupted".equals(e.getMessage())) {
// verify transaction state on coordinator before retrying
}
} Prevention
- Use async() / commitAsync() instead of blocking commit() in executor-managed threads
- Complete transactions before initiating shutdown
- Avoid interrupting threads that hold open transactions
- Treat an interrupted commit as outcome-unknown; reconcile state before retry
When it happens
Trigger: Calling commit() on a thread that gets interrupted while blocked in v4Transaction.commit().get() — e.g. executor shutdown, task cancellation, or another thread calling Thread.interrupt().
Common situations: Shutting down an application or executor while a transaction commit is pending; timeout-based task cancellation interrupting worker threads; request-handling threads interrupted by a web server during graceful shutdown.
Related errors
- Abort interrupted
- Receive interrupted
- Concurrent modification
- Invalid txnId key:
- Transaction pending ack replay error with illegal state :
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/00c50faec83f7363.
Report an issue: GitHub.