{"record":{"id":"14a4065eae39e3c5","repo":"aeron-io/aeron","slug":"service-count-must-be-zero-when-consensusmoduleextension-is","errorCode":null,"errorMessage":"service count must be zero when ConsensusModuleExtension is enabled","messagePattern":"service count must be zero when ConsensusModuleExtension is enabled","errorType":"validation","errorClass":"ClusterException","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java","lineNumber":2154,"sourceCode":"                logPublisher = new LogPublisher(logChannel());\n            }\n\n            if (null == egressPublisher)\n            {\n                egressPublisher = new EgressPublisher(leaderHeartbeatTimeoutNs);\n            }\n\n            final ChannelUri channelUri = parse(logChannel());\n            isLogMdc = channelUri.isUdp() && null == channelUri.get(ENDPOINT_PARAM_NAME);\n\n            if (null == consensusModuleExtension)\n            {\n                consensusModuleExtension = Configuration.newConsensusModuleExtension();\n            }\n\n            if (null != consensusModuleExtension && 0 != serviceCount)\n            {\n                throw new ClusterException(\"service count must be zero when ConsensusModuleExtension is enabled\");\n            }\n            else if (null == consensusModuleExtension && 0 == serviceCount)\n            {\n                throw new ClusterException(\"zero services are only supported when ConsensusModuleExtension is enabled\");\n            }\n\n            concludeMarkFile();\n\n            if (CommonContext.shouldPrintConfigurationOnStart())\n            {\n                System.out.println(this);\n            }\n        }\n\n        /**\n         * Has the context had the {@link #conclude()} method called.\n         *\n         * @return true of the {@link #conclude()} method has been called.","sourceCodeStart":2136,"sourceCodeEnd":2172,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java#L2136-L2172","documentation":"ConsensusModuleExtension is an alternative mode where the module itself provides the clustered service logic; it is incompatible with separately configured services. conclude() throws if a consensusModuleExtension was instantiated while serviceCount != 0.","triggerScenarios":"Configuration resolves a non-null ConsensusModuleExtension (Configuration.newConsensusModuleExtension() / property) while serviceCount is nonzero — e.g. the extension property is set in the environment while the app also registers clustered services.","commonSituations":"Leftover aeron.cluster.extension system property from another deployment; container configuration combining service JARs with an extension build; test fixtures leaking properties via System.setProperty.","solutions":["Remove the consensus module extension configuration property so the extension is not loaded.","Or set serviceCount to 0 (do not register ClusteredServiceContainer instances) if you intend to run the extension.","Search the launch environment/properties for whatever enables newConsensusModuleExtension and remove it."],"exampleFix":"// before\nSystem.setProperty(\"aeron.cluster.consensus.module.extension\", \"com.acme.MyExtension\");\ncontainerContext.serviceCount(2);\n// after\n// extension mode: no services\ncontainerContext.serviceCount(0);\n// or service mode: unset the extension property","handlingStrategy":"validation","validationCode":"boolean extensionEnabled = null != Configuration.newConsensusModuleExtension();\nif (extensionEnabled && ctx.serviceCount() != 0) {\n    throw new IllegalArgumentException(\"unset the extension property or set serviceCount=0\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one mode: extension OR clustered services, never both","Grep deployment properties for extension flags","Isolate System properties per test to avoid leaks"],"tags":["aeron-cluster","configuration","extension","conflicting-options"],"backgroundTag":"conflicting-config-options","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"}