aeron-io/aeron · error · InvalidChannelException
option conflicts with existing subscription: rejoin=
Error message
option conflicts with existing subscription: rejoin=${isRejoin} existingChannel=${existingChannel} channel=${channel} What it means
Subscriptions that share a channel endpoint and streamId in one Aeron client must also agree on the 'rejoin' option (whether a lost image re-joins after going unavailable). The driver throws this InvalidChannelException when a new subscription matches an existing one (channel endpoint, streamId, tag) but sets a different rejoin value.
Solutions
- Use the same rejoin value for all subscriptions on the same channel/streamId
- Close the existing conflicting subscription before adding the new one
- Separate the conflicting subscriptions onto different streams or channels with distinct endpoints
- Standardize URI templates application-wide for reliability/rejoin tuning
Example fix
// before
aeron.addSubscription("aeron:udp?endpoint=localhost:40456|rejoin=true", 1001);
// after (match existing)
aeron.addSubscription("aeron:udp?endpoint=localhost:40456|rejoin=false", 1001); Defensive patterns
Strategy: try-catch
Validate before calling
boolean rejoin = Boolean.parseBoolean(uriParam(channel, "rejoin", "true")); // ensure all subscriptions on this endpoint/streamId use the same rejoin value
Try / catch
try { aeron.addSubscription(channel, streamId, handler, unavailableHandler); } catch (InvalidChannelException e) { if (e.getMessage().contains("rejoin=")) { log.error("rejoin mismatch on {}: {}", channel, e.getMessage()); } throw e; } Prevention
- Set rejoin explicitly (same value) in every URI for a shared stream
- Avoid mixing default rejoin with explicit rejoin=false URIs
- Use distinct streamIds when different rejoin semantics are required
- Keep channel config in shared constants
When it happens
Trigger: Calling Aeron.addSubscription with a URI whose rejoin=true/false differs from an existing matching subscription on the same endpoint/streamId, e.g. adding "aeron:udp?endpoint=h:40456|rejoin=true" when "...|rejoin=false" is already subscribed.
Common situations: Mixing default (rejoin=true) with an explicitly disabled rejoin URI; gradual migration where one component sets rejoin=false for stable streams and another uses defaults; duplicated subscribe logic with divergent tuning flags.
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
- option conflicts with existing subscription: reliable=
- option conflicts with existing subscription: isResponse=
- option conflicts with existing subscription
- option conflicts with existing subscription
- = does not match existing value of : existingChannel=…
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/1a8ce8404a825dca.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java:1630
validateUdpChannelAgainstReceiveChannelEndpoint(params, udpChannel, channelEndpoint);
for (final SubscriptionLink subscription : subscriptionLinks)
{
final boolean matchesTag = !udpChannel.hasTag() || channelEndpoint.matchesTag(udpChannel);
if (matchesTag && subscription.matches(channelEndpoint, streamId, params))
{
if (params.isReliable != subscription.isReliable())
{
throw new InvalidChannelException(
"option conflicts with existing subscription: reliable=" + params.isReliable +
" existingChannel=" + subscription.channel() + " channel=" +
udpChannel.originalUriString());
}
if (params.isRejoin != subscription.isRejoin())
{
throw new InvalidChannelException(
"option conflicts with existing subscription: rejoin=" + params.isRejoin +
" existingChannel=" + subscription.channel() + " channel=" +
udpChannel.originalUriString());
}
if (params.isResponse != subscription.isResponse())
{
throw new InvalidChannelException(
"option conflicts with existing subscription: isResponse=" + params.isResponse +
" existingChannel=" + subscription.channel() + " channel=" +
udpChannel.originalUriString());
}
}
}
}
}
private void linkMatchingImages(final SubscriptionLink subscriptionLink)View on GitHub (pinned to 6d60124e15)