aeron-io/aeron · error · ClusterException

Aeron client must use conductor agent invoker

Error message

Aeron client must use conductor agent invoker

What it means

The cluster drives the Aeron client from its consensus agent loop, so conclude() requires the client to be configured with useConductorAgentInvoker(true) — the client's conductor must run inside the cluster thread rather than on its own thread. A shared client using its own conductor thread is rejected with a ClusterException.

Solutions

  1. Create a dedicated client for the cluster: Aeron.connect(new Aeron.Context().useConductorAgentInvoker(true)...)
  2. Or omit ctx.aeron(...) so the ConsensusModule constructs a compliant client itself
  3. If sharing is required, ensure invoker mode is on and invoke aeron.conductorAgentInvoker().invoke() from the cluster thread

Example fix

// before
Aeron aeron = Aeron.connect(new Aeron.Context());
ctx.aeron(aeron); // own conductor thread
// after
Aeron aeron = Aeron.connect(new Aeron.Context()
    .useConductorAgentInvoker(true));
ctx.aeron(aeron);
Defensive patterns

Strategy: validation

Validate before calling

if (!aeron.context().useConductorAgentInvoker()) {
    throw new IllegalStateException("shared Aeron client must be created with useConductorAgentInvoker(true)");
}

Type guard

boolean usesAgentInvoker(Aeron aeron) { return aeron.context().useConductorAgentInvoker(); }

Try / catch

try { ctx.conclude(); } catch (ClusterException e) { if (e.getMessage().contains("conductor agent invoker")) { /* recreate client in invoker mode */ } }

Prevention

When it happens

Trigger: Passing a pre-created Aeron client (ctx.aeron(client)) whose Aeron.Context was not built with useConductorAgentInvoker(true).

Common situations: Reusing the application's standard Aeron client for the ConsensusModule; migrating from standalone Aeron usage to clustered; copying Aeron.connect code from non-cluster examples.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

                        clusterId,
                        ConsensusModuleVersion.VERSION,
                        ConsensusModuleVersion.GIT_SHA);
                }
            }

            if (null == ingressChannel)
            {
                throw new ClusterException("ingressChannel must be specified");
            }

            if (!(aeron.context().subscriberErrorHandler() instanceof RethrowingErrorHandler))
            {
                throw new ClusterException("Aeron client must use a RethrowingErrorHandler");
            }

            if (!aeron.context().useConductorAgentInvoker())
            {
                throw new ClusterException("Aeron client must use conductor agent invoker");
            }

            if (null == errorCounter)
            {
                throw new ClusterException("error counter must be supplied if aeron client is");
            }

            if (null == countedErrorHandler)
            {
                countedErrorHandler = new CountedErrorHandler(errorHandler, errorCounter);
                if (ownsAeronClient)
                {
                    aeron.context().errorHandler(countedErrorHandler);
                }
            }

            if (null == moduleStateCounter)
            {

View on GitHub (pinned to 6d60124e15)