aeron-io/aeron · error · IllegalStateException
existing publication has different spiesSimulateConnection…
Error message
existing publication has different spiesSimulateConnection: existing=<existing> requested=<requested> existingChannel=<existingChannel> channel=<channel>
What it means
Aeron throws this IllegalStateException when adding a publication on a channel that already has a publication (matched by channel/streamId) whose `spiesSimulateConnection` URI parameter differs from the newly requested value. Parameters of publications sharing the same network channel must be consistent, so the driver rejects the conflicting add instead of silently merging settings.
Solutions
- Align the spiesSimulateConnection value in the new addPublication call with the existing publication's value shown in the message
- Close the existing publication (or restart the client/driver) before adding one with different params
- Centralize channel URI construction so the param is defined in one place
- Verify both sides pass the same explicit value rather than relying on defaults
Example fix
// before
aeron.addPublication("aeron:udp?endpoint=224.0.1.1:40456|spiesSimulateConnection=false", 1001);
aeron.addExclusivePublication("aeron:udp?endpoint=224.0.1.1:40456|spiesSimulateConnection=true", 1001);
// after
aeron.addPublication("aeron:udp?endpoint=224.0.1.1:40456|spiesSimulateConnection=true", 1001);
aeron.addExclusivePublication("aeron:udp?endpoint=224.0.1.1:40456|spiesSimulateConnection=true", 1001); Defensive patterns
Strategy: validation
Validate before calling
if (existingParams != null && existingParams.spiesSimulateConnection != requestedSpiesSimulateConnection) {
throw new IllegalArgumentException("spiesSimulateConnection must match existing publication on " + channel);
} Try / catch
try { publication = aeron.addPublication(uri, streamId); }
catch (IllegalStateException e) {
if (e.getMessage().contains("spiesSimulateConnection")) {
publication = aeron.addPublication(reuseExistingChannelParams(uri), streamId);
} else throw e;
} Prevention
- Build all channel URIs from a single shared config object
- Always set spiesSimulateConnection explicitly, never rely on defaults
- Reuse one ChannelUriStringBuilder per logical channel
When it happens
Trigger: Calling Aeron.addPublication/addExclusivePublication with a URI whose existing counterpart was added earlier with the opposite `spiesSimulateConnection=true|false` value on the same channel and stream.
Common situations: Mixing app code (spies enabled for testing tools like Aeron Archive replays) with config-driven code (spies disabled); changing the driver-level default between restarts while publications persist; a shared channel string constructed in two places with divergent params.
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
- invalid length:
- Aeron client instance must set…
- Aeron client must use a RethrowingErrorHandler
- segment file length not a power of 2
- segment file length not in valid range
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/04b30e3268254c42.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/PublicationParams.java:368
{
throw new IllegalStateException(formatMatchError(
TERM_OFFSET_PARAM_NAME,
String.valueOf(existingTermOffset),
String.valueOf(params.termOffset),
existingChannel,
channelUri.toString()));
}
}
static void validateSpiesSimulateConnection(
final PublicationParams params,
final boolean existingSpiesSimulateConnection,
final String channel,
final String existingChannel)
{
if (params.spiesSimulateConnection != existingSpiesSimulateConnection)
{
throw new IllegalStateException("existing publication has different spiesSimulateConnection: existing=" +
existingSpiesSimulateConnection + " requested=" + params.spiesSimulateConnection +
" existingChannel=" + existingChannel + " channel=" + channel);
}
}
static void validateMtuForSndbuf(
final PublicationParams params,
final int channelSocketSndbufLength,
final MediaDriver.Context ctx,
final String channel,
final String existingChannel)
{
if (0 != channelSocketSndbufLength && params.mtuLength > channelSocketSndbufLength)
{
throw new IllegalStateException(
"MTU greater than SO_SNDBUF for channel: mtu=" + params.mtuLength +
" so-sndbuf=" + channelSocketSndbufLength +
(null == existingChannel ? "" : (" existingChannel=" + existingChannel)) +View on GitHub (pinned to 6d60124e15)