aeron-io/aeron · error · IllegalStateException
existing publication has different 'mtu-length': existing=
Error message
existing publication has different 'mtu-length': existing={existingValue} requested={newValue} existingChannel={existingChannelUri} channel={newChannelUri} What it means
When reusing an existing publication's log buffer (same stream on the same channel), the driver checks that any parameter explicitly present in the new channel URI matches the existing publication. PublicationParams.confirmMatch throws IllegalStateException when the URI specifies mtu-length but the existing log's MTU differs — Aeron will not silently re-configure a live publication.
Solutions
- Make the new channel URI identical to the existing one (same mtu-length) so publication reuse succeeds.
- Remove mtu-length from the URI entirely; note the check only fires when the URI explicitly contains mtu-length.
- Close the existing publication before adding one with the new MTU.
- Canonicalize URIs in application code (parse with ChannelUri and compare params) before addPublication.
Example fix
// before: conflicting MTU on reuse
aeron.addPublication("aeron:udp?endpoint=localhost:40456|mtu-length=8k", 1001); // existing runs 16k
// after
aeron.addPublication("aeron:udp?endpoint=localhost:40456|mtu-length=16k", 1001); Defensive patterns
Strategy: try-catch
Validate before calling
ChannelUri uri = ChannelUri.parse(newChannel);
String requestedMtu = uri.get("mtu-length");
// only compare when explicitly present; otherwise reuse succeeds
if (requestedMtu != null && existingMtu != Integer.parseInt(requestedMtu)) {
newChannel = setParam(newChannel, "mtu-length", String.valueOf(existingMtu));
} Try / catch
try {
pub = aeron.addPublication(channel, streamId);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("existing publication has different 'mtu-length'")) {
throw new PublicationMismatchException("MTU differs from live publication", e);
}
throw e;
} Prevention
- Use one canonical URI per stream across all code paths
- Parse and diff ChannelUri params against the live publication before addPublication
- Avoid embedding mtu-length unless you control every publisher to the stream
When it happens
Trigger: A second addPublication call on a channel URI containing mtu-length while an existing publication for the same channel/session already runs with a different MTU (existing log buffer mtuLength != params.mtuLength).
Common situations: Two parts of an app adding the 'same' publication with slightly different URIs (one with mtu-length=8k, one without or with 16k); reconfiguring MTU after restart while old publication lingers; test harness vs prod URI drift.
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
- existing publication has different 'term-length': existing=
- formatMatchError(paramName, existingValue, paramsValue…
- formatMatchError(SESSION_ID_PARAM_NAME, existingSessionId…
- formatMatchError(INITIAL_TERM_ID_PARAM_NAME…
- formatMatchError(TERM_ID_PARAM_NAME, existingTermId…
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/9adf7f4c33a26b03.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/PublicationParams.java:301
return "existing publication has different '" + paramName + "': existing=" +
existingValue + " requested=" + newValue + " existingChannel=" + existingChannelUri +
" channel=" + newChannelUri;
}
static void confirmMatch(
final ChannelUri channelUri,
final PublicationParams params,
final RawLog rawLog,
final int existingSessionId,
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)View on GitHub (pinned to 6d60124e15)