apache/kafka · error · IllegalStateException
There is no open transaction.
Error message
There is no open transaction.
What it means
Thrown by MockProducer.verifyTransactionInFlight() as an IllegalStateException when commitTransaction(), abortTransaction(), or sendOffsetsToTransaction() is called without an open transaction. The `transactionInFlight` flag is set true by beginTransaction() and reset to false by commit/abort, so calling commit/abort/sendOffsets outside an open begin→commit window is rejected. It mirrors the real producer's requirement that exactly one transaction be in progress when these operations run.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java:312
throw new IllegalStateException("MockProducer is already closed.");
}
}
private synchronized void verifyNotFenced() {
if (this.producerFenced) {
throw new ProducerFencedException("MockProducer is fenced.");
}
}
private void verifyTransactionsInitialized() {
if (!this.transactionInitialized) {
throw new IllegalStateException("MockProducer hasn't been initialized for transactions.");
}
}
private void verifyTransactionInFlight() {
if (!this.transactionInFlight) {
throw new IllegalStateException("There is no open transaction.");
}
}
/**
* Adds the record to the list of sent records. The {@link RecordMetadata} returned will be immediately satisfied.
*
* @see #history()
*/
@Override
public synchronized Future<RecordMetadata> send(ProducerRecord<K, V> record) {
return send(record, null);
}
/**
* Adds the record to the list of sent records.
*
* @see #history()
*/View on GitHub (pinned to c31c9215e1)
Solutions
- Ensure every commitTransaction()/abortTransaction()/sendOffsetsToTransaction() is preceded by a successful beginTransaction() in the same logical transaction.
- Guard catch-block cleanup (abortTransaction()) with a check on producer.transactionInFlight() before calling abort.
- Restructure loops to begin → send → commit each iteration, not send → commit → begin.
- If using completeTransaction(PreparedTxnState), call beginTransaction() first then prepareTransaction() before completeTransaction().
Example fix
// before producer.initTransactions(false); producer.commitTransaction(); // IllegalStateException // after producer.initTransactions(false); producer.beginTransaction(); producer.send(record); producer.commitTransaction();
Defensive patterns
Strategy: validation
Validate before calling
// Guard every commit/abort/send-in-transaction behind an open-txn check
// tracked in your own flag (MockProducer exposes no isOpen() for this).
boolean txnOpen = false;
void begin(MockProducer<?,?> p) { p.beginTransaction(); txnOpen = true; }
void commit(MockProducer<?,?> p) {
if (!txnOpen) return; // or throw your own domain error
p.commitTransaction();
txnOpen = false;
} Prevention
- Mirror beginTransaction()/commitTransaction() in a local state flag so you never call commit without a begin.
- Reject double-commit and commit-without-begin at the call site with your own precondition.
- In tests, sequence calls as init -> begin -> send -> commit; never skip begin.
- Reset your local txn flag whenever you catch a fenced/closed error.
When it happens
Trigger: Calling commitTransaction(), abortTransaction(), sendOffsetsToTransaction(Map,ConsumerGroupMetadata), prepareTransaction(), or completeTransaction(PreparedTxnState) before beginTransaction() or after the previous transaction was already committed/aborted (which clears transactionInFlight at lines 247/268). The guard is at line 310-314.
Common situations: A loop that sends and commits per message but forgets to beginTransaction() each iteration; calling abortTransaction() in a catch block when no transaction was ever started (e.g. beginTransaction() itself threw); mixing auto-commit semantics with explicit commit; a retry path that re-commits after a successful commit.
Related errors
- MockProducer is already closed.
- MockProducer is fenced.
- MockProducer hasn't been initialized for transactions.
- clientInstanceId not set
- TransactionalId `{transactionalId}` was not included in the
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/00ce1ba8ee8ba493.json.
Report an issue: GitHub.