aeron-io/aeron · error · ConfigurationException

logChannel must not contain

Error message

logChannel must not contain: <initialTermId param name>

What it means

validateLogChannel() parses the configured logChannel URI and rejects parameters like initialTermId, because the cluster must control log buffer term positioning to keep all members' logs identical. A ConfigurationException is thrown naming the offending parameter.

Solutions

  1. Remove initialTermId from the logChannel URI.
  2. Let the cluster elect/reset term parameters itself; do not pin log buffer positions.
  3. Keep only allowed params (endpoint, control-mode, etc.) in the log channel.

Example fix

// before
ctx.logChannel("aeron:udp?endpoint=localhost:20000|initialTermId=0");
// after
ctx.logChannel("aeron:udp?endpoint=localhost:20000");
Defensive patterns

Strategy: validation

Validate before calling

ChannelUri uri = ChannelUri.parse(logChannel);
if (uri.containsKey("initialTermId")) {
    throw new IllegalArgumentException("logChannel must not contain initialTermId");
}

Prevention

When it happens

Trigger: Configuring ConsensusModule.Context.logChannel(...) (or the log channel property) with a URI containing initialTermId, e.g. 'aeron:udp?endpoint=...|initialTermId=0'.

Common situations: Reusing a publication/subscription channel URI that was tuned for a plain Aeron stream; copying channel strings from other Aeron components where initial term params are legal.

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/92895ff314438028. Report an issue: GitHub.

Appendix: source

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

                    0,
                    findNextPositivePowerOfTwo(
                        clusterClock.timeUnit().convert(wheelTickResolutionNs, TimeUnit.NANOSECONDS)),
                    ticksPerWheel);
            }
            else if (PriorityHeapTimerServiceSupplier.class.getName().equals(timeServiceClassName))
            {
                return new PriorityHeapTimerServiceSupplier();
            }

            throw new ClusterException("invalid TimerServiceSupplier: " + timeServiceClassName);
        }

        private void validateLogChannel()
        {
            final ChannelUri logChannelUri = parse(logChannel);
            if (logChannelUri.containsKey(INITIAL_TERM_ID_PARAM_NAME))
            {
                throw new ConfigurationException("logChannel must not contain: " + INITIAL_TERM_ID_PARAM_NAME);
            }
            if (logChannelUri.containsKey(TERM_ID_PARAM_NAME))
            {
                throw new ConfigurationException("logChannel must not contain: " + TERM_ID_PARAM_NAME);
            }
            if (logChannelUri.containsKey(TERM_OFFSET_PARAM_NAME))
            {
                throw new ConfigurationException("logChannel must not contain: " + TERM_OFFSET_PARAM_NAME);
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String toString()
        {
            return "ConsensusModule.Context" +

View on GitHub (pinned to 6d60124e15)