apache/pulsar · warning · PulsarClientException
Abort interrupted
Error message
Abort interrupted
What it means
TransactionV5.abort() blocks on the underlying v4 transaction's abort future. If the waiting thread is interrupted during that wait, the interrupt flag is restored and a PulsarClientException with the fixed message "Abort interrupted" is thrown. The abort may still have completed server-side; only the caller's wait was cancelled.
Source
Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/TransactionV5.java:64
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);
}
}
@Override
public AsyncTransaction async() {
return asyncView;
}
@Override
public State state() {
return switch (v4Transaction.getState()) {
case OPEN -> State.OPEN;
case COMMITTING -> State.COMMITTING;
case ABORTING -> State.ABORTING;
case COMMITTED -> State.COMMITTED;View on GitHub (pinned to 820761864e)
Solutions
- Prefer asyncView.async().abortAsync() to avoid blocking waits that can be interrupted.
- Ensure threads performing aborts are not interrupted during shutdown; drain pending aborts before terminating executors.
- After an interrupted abort, verify the transaction state on the coordinator; it may already be aborted — do not blindly retry commit.
Example fix
// before
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new PulsarClientException("Abort interrupted", e);
}
// after
// caller-side: avoid interrupting aborts
Executors.newSingleThreadExecutor().submit(() -> {
try { txn.abort(); } catch (PulsarClientException e) { log.warn("abort issue", e); }
}); Defensive patterns
Strategy: try-catch
Validate before calling
if (Thread.currentThread().isInterrupted()) {
log.warn("thread interrupted before abort; transaction left to TTL expiry");
return;
} Try / catch
try {
txn.abort();
} catch (PulsarClientException e) {
if ("Abort interrupted".equals(e.getMessage())) {
// abort may have completed; check state before retry
}
} Prevention
- Use abortAsync() to avoid interruptible blocking waits
- Perform rollbacks in a dedicated, non-interrupted cleanup path
- Await pending aborts before shutting down executors
- Remember transaction TTL expiry aborts server-side; interrupted aborts often self-resolve
When it happens
Trigger: Calling abort() on a thread interrupted while blocked in v4Transaction.abort().get() — executor shutdown, cancellation, or an explicit interrupt from another thread.
Common situations: Rollback during application shutdown when the worker thread is interrupted; timeout watchdogs interrupting threads stuck on abort; test frameworks cancelling blocked cleanup threads.
Related errors
- Commit interrupted
- (wraps abort failure cause message)
- Receive interrupted
- 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/21612e01d28fa4b2.
Report an issue: GitHub.