apache/pulsar · error · InvalidTxnStatusException

Transaction recover tracker`

Error message

Transaction recover tracker`

What it means

TransactionRecoverTrackerImpl.updateTransactionStatus replays entries from the transaction log and applies COMMITTING/ABORTING/COMMITTED/ABORTED status changes. It throws InvalidTxnStatusException when the replayed operation/status is unknown, indicating the transaction log contains metadata this tracker cannot interpret. This is a fail-fast guard so a corrupt or foreign log entry does not silently misstate a transaction's status.

Source

Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/transaction/recover/TransactionRecoverTrackerImpl.java:106

    @Override
    public void updateTransactionStatus(long sequenceId, TxnStatus txnStatus) throws InvalidTxnStatusException {
        switch (txnStatus) {
            case COMMITTING:
                openTransactions.remove(sequenceId);
                committingTransactions.add(sequenceId);
                break;
            case ABORTING:
                openTransactions.remove(sequenceId);
                abortingTransactions.add(sequenceId);
                break;
            case ABORTED:
                abortingTransactions.remove(sequenceId);
                break;
            case COMMITTED:
                committingTransactions.remove(sequenceId);
                break;
            default:
                throw new InvalidTxnStatusException("Transaction recover tracker`"
                        + new TxnID(tcId, sequenceId) + "` load replay metadata operation "
                        + "from transaction log with unknown operation");
        }
    }

    @Override
    public void handleOpenStatusTransaction(long sequenceId, long timeout) {
        openTransactions.put(sequenceId, timeout);
    }

    @Override
    public void appendOpenTransactionToTimeoutTracker() {
        openTransactions.forEach(timeoutTracker::replayAddTransaction);
    }

    @Override
    public void handleCommittingAndAbortingTransaction() {
        committingTransactions.forEach(k ->

View on GitHub (pinned to 820761864e)

Solutions

  1. Identify the tcId/sequenceId in the message and inspect the corresponding transaction log entry
  2. Confirm all brokers run a consistent Pulsar version that understands the log's operation codes
  3. Check the transaction log ledger for corruption; use managed-ledger recovery/repair tooling if entries are damaged
  4. If corruption is confirmed, move the affected transaction log to a recovery ledger per Pulsar transaction recovery docs and restart
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: read the transaction log entry's op field and confirm it is one of
// COMMITTING, ABORTING, COMMITTED, ABORTED before invoking updateTransactionStatus.

Try / catch

try {
    tracker.updateTransactionStatus(tcId, sequenceId, op);
} catch (InvalidTxnStatusException e) {
    log.error("Unknown transaction log operation for txn {}:{}", tcId, sequenceId, e);
    // stop recovery and escalate for manual ledger inspection
}

Prevention

When it happens

Trigger: Replaying a transaction log entry whose op/status is not one of COMMITTING, ABORTING, COMMITTED, ABORTED — typically a corrupt entry, a partially-written log record, or an entry written by a newer Pulsar version than the one replaying it.

Common situations: Cluster version skew during rolling upgrade; corrupted transaction log ledger after unclean broker shutdown; manual edits or tooling writing raw entries to the transaction log.

Related errors


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