Monedula

Kafka troubleshooting

Kafka transaction timed out (transaction.timeout.ms)

Kafka error · INVALID_PRODUCER_EPOCH · not retriable

org.apache.kafka.common.errors.InvalidProducerEpochException

The transaction stayed open longer than transaction.timeout.ms (default 60 seconds), so the transaction coordinator aborted it and bumped the producer epoch. There is no TRANSACTION_TIMED_OUT error code: the producer finds out on its next call, usually as InvalidProducerEpochException ("Producer attempted to produce with an old epoch"). Recreate the producer and keep transactions shorter than the timeout.

Reproduce it in the playground

The moment it happensTimed out · auto-aborted. t+2.600s

tx1 never committed. Once transaction.timeout.ms passed, the coordinator's periodic check auto-aborted it: the offset-0 record becomes an aborted range, the LSO releases to the high watermark, and tx1 is errored (the simulator calls it transaction_timed_out; Kafka bumps the epoch, so tx1's next send or commit fails with an epoch error). read_committed skips the aborted record entirely.

Open at this step: step 3, Timed out · auto-aborted

What it means

The timer starts when the first partition is added to the transaction. Every transaction.abort.timed.out.transaction.cleanup.interval.ms (default 10 seconds) the coordinator looks for transactions past their timeout, bumps the producer epoch to fence the producer, and writes abort markers, logging "Completed rollback of ongoing transaction for transactionalId orders-tx due to timeout", so read_committed consumers skip the records and the last stable offset moves on. KIP-588 proposed a dedicated TRANSACTION_TIMED_OUT error, but Kafka 4.x has none, so the producer learns about the abort indirectly. A send() in the aborted transaction fails with INVALID_PRODUCER_EPOCH (error code 47), and commitTransaction() then throws that InvalidProducerEpochException: "Producer with transactionalId 'orders-tx' and (producerId=1000, epoch=3) attempted to produce with an old epoch". A producer that sends nothing more and calls commitTransaction() directly is rejected by the coordinator instead: with ProducerFencedException on the original transaction protocol (transaction.version=1), with InvalidTxnStateException on the KIP-890 protocol (transaction.version=2), which Kafka 4.0 brokers enable by default and which also needs 4.0 or newer clients. Both are fatal for that producer. The simulator labels the error TransactionTimedOut; in scenario 04.2.4 the coordinator aborts an abandoned transaction and releases the LSO, which is the broker side of what this page describes.

Likely causes, most common first

  1. Work inside the transaction takes longer than the timeout. Processing a large poll batch, calling a slow external service, or waiting on a lock between beginTransaction() and commitTransaction() pushes the transaction past transaction.timeout.ms.
  2. The producer stalled. A long GC pause, a frozen or CPU-throttled container, or a network partition between the producer and the coordinator. KIP-588 names short client inactivity from a network partition or a long GC as the usual trigger.
  3. A transaction was left open. A code path calls beginTransaction(), then returns or throws without commitTransaction() or abortTransaction(), so nothing ends the transaction until the coordinator does. Scenario 04.2.4 reproduces this: the producer never resolves its transaction and the coordinator aborts it at the timeout.

How to fix it

What not to do

Does the client retry it?

No. The transaction is already aborted and its records will never be committed. Kafka 4.x classifies InvalidProducerEpochException as application-recoverable: close the producer, create a new one with the same transactional.id and redo the work of the aborted transaction. The exception's own Javadoc still describes recovering with abortTransaction(); the 4.x guidance (KIP-1050) is to restart the producer.

Configs involved

Reproduce it in the simulator

Sources

Related

All troubleshooting pages