apache/kafka · error · IllegalStateException
MockProducer hasn't been initialized for transactions.
Error message
MockProducer hasn't been initialized for transactions.
What it means
Thrown by MockProducer.verifyTransactionsInitialized() as an IllegalStateException when a transactional method is invoked before initTransactions() has been called. MockProducer only sets `transactionInitialized = true` inside initTransactions() (line 165); beginTransaction(), commitTransaction(), abortTransaction(), sendOffsetsToTransaction(), prepareTransaction(), completeTransaction(), and fenceProducer() all require that precondition. It mirrors the real producer's contract that the transactional.id must be resolved and the producer epoch established before any transactional work.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java:306
abortTransaction();
}
}
private synchronized void verifyNotClosed() {
if (this.closed) {
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);
}View on GitHub (pinned to c31c9215e1)
Solutions
- Call producer.initTransactions(false) (or initTransactions(true) when testing prepared-state flows) before beginTransaction/commitTransaction/etc.
- If initTransactionException was set, verify the exception was expected and that production code recovers by retrying init or aborting — do not proceed to beginTransaction after a failed init.
- Centralize the initTransactions() call in the test's @BeforeEach so every transactional test starts from an initialized producer.
- Check the production code under test: if it relies on lazy initialization, ensure that path is actually taken before the first transactional call.
Example fix
// before MockProducer<String,String> p = new MockProducer<>(); p.beginTransaction(); // IllegalStateException // after MockProducer<String,String> p = new MockProducer<>(); p.initTransactions(false); p.beginTransaction();
Defensive patterns
Strategy: validation
Validate before calling
// Call initTransactions() exactly once before any txn API.
// Track initialization locally so you never call commit/abort/prepare first.
boolean initialized = false;
void ensureTxnInit(MockProducer<?,?> p) {
if (!initialized) {
p.initTransactions();
initialized = true;
}
}
// call ensureTxnInit(producer) before beginTransaction()/completeTransaction() Prevention
- Always pair 'new MockProducer(...)' with an immediate initTransactions() if you will use transactions.
- Keep transaction lifecycle calls behind a helper that initializes on first use.
- Never assume a producer handed to you by another component has transactions initialized — check or initialize explicitly.
- In tests, assert that the first transactional call is initTransactions().
When it happens
Trigger: Calling beginTransaction(), commitTransaction(), abortTransaction(), sendOffsetsToTransaction(...), prepareTransaction(), completeTransaction(...), or fenceProducer() without first calling initTransactions(boolean) on the mock. The check happens at line 304-308 before the method does any real work.
Common situations: A test that drives transactional send/commit logic but skips the initTransactions step because the production wrapper hides it; upgrading a test from non-transactional to transactional usage without adding the init call; an initTransactions() call that threw initTransactionException (so transactionInitialized stayed false) followed by beginTransaction().
Related errors
- MockProducer is already closed.
- MockProducer is fenced.
- There is no open transaction.
- clientInstanceId not set
- Cannot add partition {topicPartition} to transaction before
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/ec23a2909226310f.json.
Report an issue: GitHub.