aeron-io/aeron · error · IllegalStateException

existing publication has different 'term-length': existing=

Error message

existing publication has different 'term-length': existing={existingValue} requested={newValue} existingChannel={existingChannelUri} channel={newChannelUri}

What it means

confirmMatch equivalent for term-length: when the new channel URI explicitly carries term-length and the already-existing publication's log buffer was created with a different term length, PublicationParams.confirmMatch throws IllegalStateException. Aeron requires that re-additions of the same publication match the original buffer geometry exactly.

Solutions

  1. Use the same term-length as the existing publication (read it from the error message: existing=...).
  2. Omit term-length from the re-add URI (the mismatch check only applies when explicitly present).
  3. Close/await closure of the existing publication, then add with the new term-length.
  4. Share one canonical URI constant across all publishers to a given stream.

Example fix

// before
aeron.addPublication("aeron:udp?endpoint=localhost:40456|term-length=64k", 1001); // existing is 1m

// after
aeron.addPublication("aeron:udp?endpoint=localhost:40456|term-length=1m", 1001);
Defensive patterns

Strategy: try-catch

Validate before calling

ChannelUri uri = ChannelUri.parse(newChannel);
String requestedTermLen = uri.get("term-length");
if (requestedTermLen != null && existingTermLength != Integer.parseInt(requestedTermLen)) {
    newChannel = setParam(newChannel, "term-length", String.valueOf(existingTermLength));
}

Try / catch

try {
    pub = aeron.addPublication(channel, streamId);
} catch (IllegalStateException e) {
    if (e.getMessage().startsWith("existing publication has different 'term-length'")) {
        throw new PublicationMismatchException("Term length differs from live publication", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: addPublication on a URI with term-length=N where a live publication for the same channel/session exists with term-length=M (M != N), e.g. one subscriber-side template says 64k and the existing one was created with 1m.

Common situations: Reconnecting a publisher after config change while the driver still holds the old publication; multiple services publishing to the same endpoint with different term-length URIs; environment-specific URI configs drifting.

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

Appendix: source

Thrown at aeron-driver/src/main/java/io/aeron/driver/PublicationParams.java:311

        final String existingChannel,
        final int existingInitialTermId,
        final int existingTermId,
        final int existingTermOffset)
    {
        final int mtuLength = LogBufferDescriptor.mtuLength(rawLog.metaData());
        if (channelUri.containsKey(MTU_LENGTH_PARAM_NAME) && mtuLength != params.mtuLength)
        {
            throw new IllegalStateException(formatMatchError(
                MTU_LENGTH_PARAM_NAME,
                String.valueOf(mtuLength),
                String.valueOf(params.mtuLength),
                existingChannel,
                channelUri.toString()));
        }

        if (channelUri.containsKey(TERM_LENGTH_PARAM_NAME) && rawLog.termLength() != params.termLength)
        {
            throw new IllegalStateException(formatMatchError(
                TERM_LENGTH_PARAM_NAME,
                String.valueOf(rawLog.termLength()),
                String.valueOf(params.termLength),
                existingChannel,
                channelUri.toString()));
        }

        if (channelUri.containsKey(SESSION_ID_PARAM_NAME) && params.sessionId != existingSessionId)
        {
            throw new IllegalStateException(formatMatchError(
                SESSION_ID_PARAM_NAME,
                String.valueOf(existingSessionId),
                String.valueOf(params.sessionId),
                existingChannel,
                channelUri.toString()));
        }

        if (channelUri.containsKey(INITIAL_TERM_ID_PARAM_NAME) && params.initialTermId != existingInitialTermId)

View on GitHub (pinned to 6d60124e15)