apache/pulsar · error · PulsarClientException

(wraps commit failure cause message)

Error message

(wraps commit failure cause message)

What it means

TransactionV5.commit() blocks on the v4 transaction's commit future; when that future completes with ExecutionException, the cause is extracted (falling back to the ExecutionException itself if the cause is null) and rethrown as a PulsarClientException whose message is the underlying cause's message. This error therefore reports the broker/client's real reason the commit failed.

Source

Thrown at pulsar-client-v5/src/main/java/org/apache/pulsar/client/impl/v5/TransactionV5.java:54

    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);
        }
    }

    @Override
    public AsyncTransaction async() {

View on GitHub (pinned to 820761864e)

Solutions

  1. Read the wrapped cause (getCause()) for the broker's actual rejection reason.
  2. Commit within the transaction timeout — increase transactionTimeoutSeconds if operations take long.
  3. Ensure only one thread commits/aborts the transaction; guard with ownership or serialization.
  4. Check broker availability and transaction coordinator health; retry with a new transaction if the old one is definitively failed.

Example fix

// before
txn.commit(); // may throw with opaque broker message
// after
try {
    txn.commit();
} catch (PulsarClientException e) {
    Throwable root = e.getCause() != null ? e.getCause() : e;
    if (root instanceof TransactionInvalidException) {
        startNewTransactionAndRetry();
    } else {
        throw e;
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (txn == null || !txn.isOpen()) throw new IllegalStateException("transaction not open; cannot commit");
if (System.currentTimeMillis() - txnStartMillis > txnTimeoutMillis) log.warn("committing after timeout risk");

Type guard

static boolean isCommitRejected(Throwable t) {
    Throwable c = t;
    while (c != null) { if (c.getMessage() != null && c.getMessage().contains("Transaction")) return true; c = c.getCause(); }
    return false;
}

Try / catch

try {
    txn.commit();
} catch (PulsarClientException e) {
    Throwable cause = e.getCause() != null ? e.getCause() : e;
    log.error("commit failed: {}", cause.getMessage(), cause);
}

Prevention

When it happens

Trigger: Calling commit() when the underlying v4 commit future fails — broker rejected the commit, transaction timed out or was already aborted, coordinator unavailable, or the producer/consumer attached to the transaction errored.

Common situations: Transaction timeout exceeded (committing after the TTL); transaction coordinator restarted or unavailable; committing a transaction that another thread already aborted; broker-side authorization or ledger failures.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/7f58c06f65977104. Report an issue: GitHub.