{"id":"1c49e7b871001bc3","repo":"apache/kafka","slug":"mockproducer-has-already-been-initialized-for-tran","errorCode":null,"errorMessage":"MockProducer has already been initialized for transactions.","messagePattern":"MockProducer has already been initialized for transactions\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java","lineNumber":160,"sourceCode":"                        final Serializer<V> valueSerializer) {\n        this(Cluster.empty(), autoComplete, partitioner, keySerializer, valueSerializer);\n    }\n\n    /**\n     * Create a new mock producer with invented metadata.\n     *\n     * Equivalent to {@link #MockProducer(Cluster, boolean, Partitioner, Serializer, Serializer) new MockProducer(Cluster.empty(), false, null, null, null)}\n     */\n    public MockProducer() {\n        this(Cluster.empty(), false, null, null, null);\n    }\n\n    @Override\n    public void initTransactions(boolean keepPreparedTxn) {\n        verifyNotClosed();\n        verifyNotFenced();\n        if (this.transactionInitialized) {\n            throw new IllegalStateException(\"MockProducer has already been initialized for transactions.\");\n        }\n        if (this.initTransactionException != null) {\n            throw this.initTransactionException;\n        }\n        this.transactionInitialized = true;\n        this.transactionInFlight = false;\n        this.transactionCommitted = false;\n        this.transactionAborted = false;\n        this.sentOffsets = false;\n    }\n\n    @Override\n    public void beginTransaction() throws ProducerFencedException {\n        verifyNotClosed();\n        verifyNotFenced();\n        verifyTransactionsInitialized();\n\n        if (this.beginTransactionException != null) {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java#L142-L178","documentation":"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.","triggerScenarios":"Calling mockProducer.initTransactions() or initTransactions(true) a second time on the same MockProducer instance.","commonSituations":"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.","solutions":["Create a fresh MockProducer for each test (in @BeforeEach) rather than re-initializing.","Move initTransactions() out of test code if the test base already calls it.","Guard with a flag or use @BeforeEach to reset state by constructing a new instance.","If you genuinely need to re-init, discard the old MockProducer and construct a new one."],"exampleFix":"// before\nprivate final MockProducer<String,String> mp = new MockProducer<>();\n\n@BeforeEach void setup()  { mp.initTransactions(); }\n@Test   void myTest()    { mp.initTransactions(); /* throws */ }\n\n// after\nprivate MockProducer<String,String> mp;\n\n@BeforeEach void setup() {\n    mp = new MockProducer<>();   // fresh per test\n    mp.initTransactions();       // called exactly once per instance\n}","handlingStrategy":"validation","validationCode":"// MockProducer.initTransactions(keepPreparedTxn) throws IllegalStateException\n// if already initialized. In tests, call it exactly once per MockProducer\n// instance and track it.\nMockProducer mp = new MockProducer(Cluster.empty(), false, null, null, null);\n// track init in the test, or wrap:\njava.util.concurrent.atomic.AtomicBoolean inited = new java.util.concurrent.atomic.AtomicBoolean();\n\nvoid initOnce(MockProducer m, boolean keepPrepared) {\n    if (!inited.compareAndSet(false, true)) {\n        throw new IllegalStateException(\"initTransactions already called on this mock\");\n    }\n    m.initTransactions(keepPrepared);\n}","typeGuard":null,"tryCatchPattern":"try {\n    mockProducer.initTransactions();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"already been initialized\")) {\n        // expected if the @BeforeEach already initialized; ignore in tests\n        return;\n    }\n    throw e;\n}","preventionTips":["Create a fresh MockProducer per test method (e.g. in @BeforeEach) so init state never leaks across tests.","Call initTransactions() exactly once per mock; centralize it in test setup.","Do not reuse a static MockProducer across tests; its transaction flags persist.","Assert the expected transaction sequence in tests with the mock's history methods."],"tags":["producer","mock","testing","transactions"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}