aeron-io/aeron · error · ClusterException

ConsensusModule.Context.clusterMembers must be set

Error message

ConsensusModule.Context.clusterMembers must be set

What it means

A ConsensusModule needs the full list of cluster member endpoints to canvas for a leader and form/maintain consensus. conclude() requires Context.clusterMembers to be explicitly set; a null value is a configuration error thrown as a ClusterException.

Solutions

  1. Call ctx.clusterMembers("memberId,clientFacingIngress,memberFacing,log,archive,events|..."), e.g. "0,localhost:20000,localhost:20001,localhost:20002,localhost:20003,localhost:20004"
  2. Set the system property aeron.cluster.cluster.members for the clusterio launcher
  3. Use ClusterMembership tools or the same string on all members with consistent member IDs

Example fix

// before
new ConsensusModule.Context()
    .ingressChannel("aeron:udp?endpoint=localhost:20000"); // no clusterMembers
// after
new ConsensusModule.Context()
    .ingressChannel("aeron:udp?endpoint=localhost:20000")
    .clusterMembers("0,localhost:20000,localhost:20001,localhost:20002,localhost:20003,localhost:20004");
Defensive patterns

Strategy: validation

Validate before calling

if (ctx.clusterMembers() == null) {
    throw new IllegalStateException("ConsensusModule.Context.clusterMembers must be set before conclude()");
}

Try / catch

try { ctx.conclude(); } catch (ClusterException e) { if (e.getMessage().contains("clusterMembers must be set")) { /* load cluster config and retry setup */ } }

Prevention

When it happens

Trigger: Building a ConsensusModule.Context (or using the standalone-cluster launcher) without calling clusterMembers(...) before conclude().

Common situations: Omitting -Daeron.cluster.cluster.members on the command line; writing a custom main() that sets channels/ports but forgets clusterMembers; migrating from single-node setups that tolerated defaults in older Aeron versions.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/0a3fd371897cdb19. Report an issue: GitHub.

Appendix: source

Thrown at aeron-cluster/src/main/java/io/aeron/cluster/ConsensusModule.java:1772

                markFileDir = markFileDir.getCanonicalFile();

                if (Strings.isEmpty(clusterServicesDirectoryName))
                {
                    clusterServicesDirectoryName = clusterDirectoryName;
                }
                else
                {
                    clusterServicesDirectoryName = new File(clusterServicesDirectoryName).getCanonicalPath();
                }
            }
            catch (final IOException ex)
            {
                throw new UncheckedIOException(ex);
            }

            if (null == clusterMembers)
            {
                throw new ClusterException("ConsensusModule.Context.clusterMembers must be set");
            }

            if (deleteDirOnStart)
            {
                IoUtil.delete(clusterDir, false);
            }

            IoUtil.ensureDirectoryExists(clusterDir, "cluster");
            IoUtil.ensureDirectoryExists(markFileDir, "mark file");

            if (startupCanvassTimeoutNs / leaderHeartbeatTimeoutNs < 2)
            {
                throw new ClusterException(
                    "startupCanvassTimeoutNs=" + startupCanvassTimeoutNs +
                    " must be a multiple of leaderHeartbeatTimeoutNs=" + leaderHeartbeatTimeoutNs);
            }

            if (null == clusterClock)

View on GitHub (pinned to 6d60124e15)