aeron-io/aeron · error · InvalidChannelException
option conflicts with existing subscription: isResponse=
Error message
option conflicts with existing subscription: isResponse=${isResponse} existingChannel=${existingChannel} channel=${channel} What it means
The 'response' option on Aeron subscriptions must be consistent across all subscriptions matching the same channel endpoint and streamId. This InvalidChannelException is thrown when a new subscription matches an existing one but sets isResponse to a different value.
Solutions
- Set the same response value on all subscriptions for that channel/streamId
- Close the conflicting existing subscription before re-adding with the new option
- Use a separate streamId or channel endpoint for response subscriptions
- Keep a single URI builder so option parity is guaranteed
Example fix
// before
aeron.addSubscription("aeron:udp?endpoint=localhost:40456", 1001); // existing, response=false
// after
aeron.addSubscription("aeron:udp?endpoint=localhost:40456|response=true", 1001); // now consistent Defensive patterns
Strategy: try-catch
Validate before calling
boolean response = channel.contains("response=true");
// ensure consistency with all other subscriptions on this channel/streamId Try / catch
try { aeron.addSubscription(channel, streamId, handler, unavailableHandler); } catch (InvalidChannelException e) { if (e.getMessage().contains("isResponse=")) { log.error("response option mismatch: {}", e.getMessage()); } throw e; } Prevention
- Apply the response= flag uniformly to all subscribers of a stream
- Only enable response=true on streams dedicated to the response-channel feature
- Do not mix legacy plain URIs with response-enabled URIs on the same stream
- Keep URIs generated from one config source
When it happens
Trigger: Adding a subscription with response=true (response channels) on a channel/streamId where a subscription with response=false (or default) already exists and matches tag/endpoint/stream, e.g. mixing "aeron:udp?endpoint=h:p|response=true" with a plain subscription.
Common situations: Enabling the response-channel feature on one subscriber while legacy subscribers on the same stream omit it; component adds a response subscription to a shared stream; copy-pasted URIs where one gained the response param.
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: rejoin=
- 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/c261bbc9ca3c3de6.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java:1638
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)
{
for (int i = 0, size = publicationImages.size(); i < size; i++)
{
final PublicationImage image = publicationImages.get(i);
if (subscriptionLink.matches(image) && image.isAcceptingSubscriptions())
{
final long registrationId = subscriptionLink.registrationId();
final long joinPosition = image.joinPosition();View on GitHub (pinned to 6d60124e15)