aeron-io/aeron · error · ConfigurationException

logChannel must not contain

Error message

logChannel must not contain: <termId param name>

What it means

Part of the same validateLogChannel() check: the logChannel URI must not contain termId, since cluster members must agree on the log's term identity and a pinned termId would break replication/recovery. A ConfigurationException naming the parameter is thrown.

Solutions

  1. Remove termId from the logChannel URI.
  2. If term positioning is needed for other streams, configure it there, not on the cluster log channel.
  3. Let the cluster manage term parameters during election and replay.

Example fix

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

Strategy: validation

Validate before calling

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

Prevention

When it happens

Trigger: logChannel URI includes termId, e.g. 'aeron:udp?endpoint=...|termId=100'.

Common situations: Copying a channel string from a standalone Aeron publication config; hand-crafted URI including term positioning params.

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/5bde0cea2d3ea090. Report an issue: GitHub.

Appendix: source

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

            }
            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" +
                "\n{" +
                "\n    isConcluded=" + isConcluded() +
                "\n    ownsAeronClient=" + ownsAeronClient +
                "\n    aeronDirectoryName='" + aeronDirectoryName + '\'' +

View on GitHub (pinned to 6d60124e15)