aeron-io/aeron · error · ConfigurationException

Must use Aeron.Context.useConductorAgentInvoker(true) when…

Error message

Must use Aeron.Context.useConductorAgentInvoker(true) when Aeron.Context.clientLock(...) is using a NoOpLock

What it means

Aeron.Context throws this ConfigurationException during configuration when a NoOpLock is set as the client lock via clientLock(...) but useConductorAgentInvoker(true) was not enabled. NoOpLock provides no mutual exclusion, which is only safe when the caller drives the conductor agent directly on the same thread (agent invoker mode); otherwise concurrent access is unsafe, so the combination is rejected.

Solutions

  1. Call ctx.useConductorAgentInvoker(true) on the same Context that uses NoOpLock
  2. Remove the NoOpLock and use the default ReentrantLock if you want the normal client thread mode
  3. Use the Convenience/ Configuration helper that pairs clientLock(true) with useConductorAgentInvoker(true) consistently

Example fix

// before
Aeron.Context ctx = new Aeron.Context()
    .clientLock(new NoOpLock());
Aeron aeron = Aeron.connect(ctx); // throws
// after
Aeron.Context ctx = new Aeron.Context()
    .clientLock(new NoOpLock())
    .useConductorAgentInvoker(true);
Aeron aeron = Aeron.connect(ctx);
Defensive patterns

Strategy: validation

Validate before calling

if (ctx instanceof Aeron.Context) { /* ensure pairing before connect */ } // validate: use NoOpLock only together with useConductorAgentInvoker(true)

Type guard

boolean lockModeConsistent(Aeron.Context ctx) { return ctx.useConductorAgentInvoker() || !(ctx.clientLock() instanceof NoOpLock); }

Try / catch

try { return Aeron.connect(ctx); } catch (ConfigurationException e) { if (e.getMessage().contains("NoOpLock")) { ctx.useConductorAgentInvoker(true); return Aeron.connect(ctx); } throw e; }

Prevention

When it happens

Trigger: Building a Context with ctx.clientLock(new NoOpLock()) (or ctx.clientLock(true) equivalent) without also calling ctx.useConductorAgentInvoker(true), then calling Aeron.connect(ctx).

Common situations: Low-latency setups that eliminate locking to avoid contention but forget to switch to conductor agent invoker mode; copying a dedicated-mode config into a client that still uses the driver thread; upgrades where NoOpLock was introduced and existing configs were not updated.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at aeron-client/src/main/java/io/aeron/Aeron.java:1184

        /**
         * This is called automatically by {@link Aeron#connect(Aeron.Context)} and its overloads.
         * There is no need to call it from a client application. It is responsible for providing default
         * values for options that are not individually changed through field setters.
         *
         * @return this for a fluent API.
         */
        @SuppressWarnings("checkstyle:methodlength")
        public Context conclude()
        {
            super.conclude();

            if (null == clientLock)
            {
                clientLock = new ReentrantLock();
            }
            else if (clientLock instanceof NoOpLock && !useConductorAgentInvoker)
            {
                throw new ConfigurationException(
                    "Must use Aeron.Context.useConductorAgentInvoker(true) when Aeron.Context.clientLock(...) " +
                    "is using a NoOpLock");
            }

            if (null != driverAgentInvoker && !useConductorAgentInvoker)
            {
                throw new ConfigurationException(
                    "Must use Aeron.Context.useConductorAgentInvoker(true) when Aeron.Context.driverAgentInvoker() " +
                    "is set");
            }

            if (clientName.length() > MAX_CLIENT_NAME_LENGTH)
            {
                throw new ConfigurationException("clientName length must <= " + MAX_CLIENT_NAME_LENGTH);
            }

            if (null == epochClock)
            {

View on GitHub (pinned to 6d60124e15)