apache/kafka · error · IllegalStateException

MockProducer has already been initialized for transactions.

Error message

MockProducer has already been initialized for transactions.

What it means

Thrown by MockProducer.initTransactions(boolean) when transactionInitialized is already true. MockProducer (used in unit tests for exactly-once/transactional code) models transactional state explicitly; initTransactions may only be called once per instance to mirror the real producer's contract that transaction initialization is a one-shot setup.

Source

Thrown at clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java:160

                        final Serializer<V> valueSerializer) {
        this(Cluster.empty(), autoComplete, partitioner, keySerializer, valueSerializer);
    }

    /**
     * Create a new mock producer with invented metadata.
     *
     * Equivalent to {@link #MockProducer(Cluster, boolean, Partitioner, Serializer, Serializer) new MockProducer(Cluster.empty(), false, null, null, null)}
     */
    public MockProducer() {
        this(Cluster.empty(), false, null, null, null);
    }

    @Override
    public void initTransactions(boolean keepPreparedTxn) {
        verifyNotClosed();
        verifyNotFenced();
        if (this.transactionInitialized) {
            throw new IllegalStateException("MockProducer has already been initialized for transactions.");
        }
        if (this.initTransactionException != null) {
            throw this.initTransactionException;
        }
        this.transactionInitialized = true;
        this.transactionInFlight = false;
        this.transactionCommitted = false;
        this.transactionAborted = false;
        this.sentOffsets = false;
    }

    @Override
    public void beginTransaction() throws ProducerFencedException {
        verifyNotClosed();
        verifyNotFenced();
        verifyTransactionsInitialized();

        if (this.beginTransactionException != null) {

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Create a fresh MockProducer for each test (in @BeforeEach) rather than re-initializing.
  2. Move initTransactions() out of test code if the test base already calls it.
  3. Guard with a flag or use @BeforeEach to reset state by constructing a new instance.
  4. If you genuinely need to re-init, discard the old MockProducer and construct a new one.

Example fix

// before
private final MockProducer<String,String> mp = new MockProducer<>();

@BeforeEach void setup()  { mp.initTransactions(); }
@Test   void myTest()    { mp.initTransactions(); /* throws */ }

// after
private MockProducer<String,String> mp;

@BeforeEach void setup() {
    mp = new MockProducer<>();   // fresh per test
    mp.initTransactions();       // called exactly once per instance
}
Defensive patterns

Strategy: validation

Validate before calling

// MockProducer.initTransactions(keepPreparedTxn) throws IllegalStateException
// if already initialized. In tests, call it exactly once per MockProducer
// instance and track it.
MockProducer mp = new MockProducer(Cluster.empty(), false, null, null, null);
// track init in the test, or wrap:
java.util.concurrent.atomic.AtomicBoolean inited = new java.util.concurrent.atomic.AtomicBoolean();

void initOnce(MockProducer m, boolean keepPrepared) {
    if (!inited.compareAndSet(false, true)) {
        throw new IllegalStateException("initTransactions already called on this mock");
    }
    m.initTransactions(keepPrepared);
}

Try / catch

try {
    mockProducer.initTransactions();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("already been initialized")) {
        // expected if the @BeforeEach already initialized; ignore in tests
        return;
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling mockProducer.initTransactions() or initTransactions(true) a second time on the same MockProducer instance.

Common situations: JUnit @BeforeEach that builds and inits a shared producer plus test code that also calls initTransactions; a test base class and a subclass both initializing; reusing a MockProducer field across parameterized test invocations without recreating it.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/1c49e7b871001bc3.json. Report an issue: GitHub.