{"record":{"id":"9b25ab4183202584","repo":"aeron-io/aeron","slug":"existing-consensus-module-detected-for-clusterid-clusterid","errorCode":null,"errorMessage":"existing consensus module detected for clusterId=<clusterId>","messagePattern":"existing consensus module detected for clusterId=<clusterId>","errorType":"exception","errorClass":"ClusterException","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java","lineNumber":1937,"sourceCode":"            {\n                throw new ClusterException(\"error counter must be supplied if aeron client is\");\n            }\n\n            if (null == countedErrorHandler)\n            {\n                countedErrorHandler = new CountedErrorHandler(errorHandler, errorCounter);\n                if (ownsAeronClient)\n                {\n                    aeron.context().errorHandler(countedErrorHandler);\n                }\n            }\n\n            if (null == moduleStateCounter)\n            {\n                final CountersReader counters = aeron.countersReader();\n                if (Aeron.NULL_VALUE != ClusterCounters.find(counters, CONSENSUS_MODULE_STATE_TYPE_ID, clusterId))\n                {\n                    throw new ClusterException(\"existing consensus module detected for clusterId=\" + clusterId);\n                }\n\n                moduleStateCounter = ClusterCounters.allocate(\n                    aeron, buffer, \"Consensus Module state\", CONSENSUS_MODULE_STATE_TYPE_ID, clusterId);\n            }\n            validateCounterTypeId(aeron, moduleStateCounter, CONSENSUS_MODULE_STATE_TYPE_ID);\n\n\n            if (null == electionStateCounter)\n            {\n                electionStateCounter = ClusterCounters.allocate(\n                    aeron, buffer, \"Cluster election state\", ELECTION_STATE_TYPE_ID, clusterId);\n            }\n            validateCounterTypeId(aeron, electionStateCounter, ELECTION_STATE_TYPE_ID);\n\n            if (null == electionCounter)\n            {\n                electionCounter = ClusterCounters.allocate(","sourceCodeStart":1919,"sourceCodeEnd":1955,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java#L1919-L1955","documentation":"During ConsensusModule startup (conclude/onStart), the module checks the Aeron driver's counters for an existing 'Consensus Module state' counter matching the configured clusterId. If one already exists, another consensus module instance is (or was) using the same driver/media driver for this cluster, so a second module would corrupt cluster state. Aeron throws ClusterException to abort the duplicate startup.","triggerScenarios":"Launching a second ConsensusModule with the same clusterId while a previous one is still connected to the same Aeron driver, or restarting after a crash that left the stale counter allocated in a still-running embedded driver.","commonSituations":"Accidentally starting two nodes in the same JVM/driver during testing; a previous ConsensusModule not fully closed (missing close()) before re-launching; embedded-driver test harnesses reusing a driver across runs; container restart where the media driver survives.","solutions":["Ensure the previous ConsensusModule/Aeron client is fully closed (close() in finally/shutdown hook) before starting a new one.","Use a distinct clusterId for each cluster/member, or connect to a different (dedicated) media driver.","If restarting after a crash, terminate the old media driver or clear its counters; for embedded drivers recreate the driver process.","If moduleStateCounter was captured externally, pass the existing counter instead of letting conclude() detect a duplicate."],"exampleFix":"// before\nAeron aeron = Aeron.connect();\nConsensusModule module = ConsensusModule.launch(moduleCtx.aeron(aeron).clusterId(0));\nConsensusModule second = ConsensusModule.launch(moduleCtx2.aeron(aeron).clusterId(0)); // throws\n// after\nConsensusModule second = ConsensusModule.launch(moduleCtx2.aeron(aeron).clusterId(1)); // distinct clusterId","handlingStrategy":"try-catch","validationCode":"// before launch\nCountersReader counters = aeron.countersReader();\nif (Aeron.NULL_VALUE != ClusterCounters.find(counters, CONSENSUS_MODULE_STATE_TYPE_ID, clusterId)) {\n    throw new IllegalStateException(\"consensus module already running for clusterId=\" + clusterId);\n}","typeGuard":null,"tryCatchPattern":"try { ConsensusModule.launch(ctx); } catch (ClusterException e) { if (e.getMessage().contains(\"existing consensus module detected\")) { closePreviousModuleAndRetry(); } else { throw e; } }","preventionTips":["Always close() the previous ConsensusModule in a shutdown hook","Use a unique clusterId per cluster in shared drivers","In tests, recreate the media driver between runs"],"tags":["aeron-cluster","startup","duplicate-instance","counters"],"backgroundTag":"address-already-in-use","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}