aeron-io/aeron · error · IllegalStateException

formatMatchError(SESSION_ID_PARAM_NAME, existingSessionId…

Error message

formatMatchError(SESSION_ID_PARAM_NAME, existingSessionId, params.sessionId, existingChannel, channelUri)

What it means

initial-term-id branch of confirmMatch: when the channel URI explicitly includes initial-term-id and the requested value differs from the existing publication's initial term id stored in its log buffer metadata, PublicationParams.confirmMatch throws IllegalStateException. Initial term id pins where the term counter starts and cannot change on reuse.

Solutions

  1. Use the same initial-term-id as the existing publication (see existing= in the message).
  2. Remove initial-term-id from the URI so the existing buffer's value is accepted.
  3. Ensure the prior publication is fully closed before adding with a new initial-term-id.
  4. Persist the chosen initial-term-id (e.g. in a ledger) so restarts reuse it rather than generating a fresh value.

Example fix

// before
"aeron:udp?endpoint=localhost:40456|initial-term-id=-42" // existing buffer has 0

// after
"aeron:udp?endpoint=localhost:40456|initial-term-id=0"
Defensive patterns

Strategy: try-catch

Validate before calling

String iti = ChannelUri.parse(channel).get("initial-term-id");
if (iti != null && existingInitialTermId != Long.decode(iti)) {
    throw new IllegalArgumentException("initial-term-id " + iti + " conflicts with existing publication " + existingInitialTermId);
}

Try / catch

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

Prevention

When it happens

Trigger: Re-adding a publication with URI initial-term-id=X while the existing log buffer was built with initial-term-id=Y; typically happens with deterministic/replayable publisher setups that hardcode initial-term-id differently across processes.

Common situations: Recording/replay systems that set initial-term-id per run; crash-restart code generating a new initial-term-id while the old publication is still registered; two app instances using the same deterministic channel config but different seeds.

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

Appendix: source

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

                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)
        {
            throw new IllegalStateException(formatMatchError(
                INITIAL_TERM_ID_PARAM_NAME,
                String.valueOf(existingInitialTermId),
                String.valueOf(params.initialTermId),
                existingChannel,
                channelUri.toString()));
        }

        if (channelUri.containsKey(TERM_ID_PARAM_NAME) && params.termId != existingTermId)
        {
            throw new IllegalStateException(formatMatchError(
                TERM_ID_PARAM_NAME,
                String.valueOf(existingTermId),
                String.valueOf(params.termId),
                existingChannel,
                channelUri.toString()));
        }

        if (channelUri.containsKey(TERM_OFFSET_PARAM_NAME) && params.termOffset != existingTermOffset)

View on GitHub (pinned to 6d60124e15)