aeron-io/aeron · error · InvalidChannelException
option conflicts with existing subscription
Error message
option conflicts with existing subscription: ${CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME}=${offset} existingChannel=${existingChannel} channel=${channel} What it means
Analogous to the send-timestamp check: when a new subscription maps to an existing ReceiveChannelEndpoint, its channel-receive-timestamp-offset param must equal that of the existing endpoint's subscription UDP channel. A mismatch is rejected with InvalidChannelException to keep receive timestamping consistent for all subscriptions sharing the endpoint.
Solutions
- Align channel-receive-timestamp-offset across all subscriptions sharing the channel
- Specify the param explicitly and identically in every channel URI string
- If different offsets are needed, use a different channel/endpoint for that subscription
- Catch InvalidChannelException on addSubscription and report the conflicting option to operators
Example fix
// before
aeron.addSubscription("aeron:udp?endpoint=224.0.1.1:40456|channel-receive-timestamp-offset=reserved", streamId);
aeron.addSubscription("aeron:udp?endpoint=224.0.1.1:40456", streamId); // mismatch -> InvalidChannelException
// after
String ch = "aeron:udp?endpoint=224.0.1.1:40456|channel-receive-timestamp-offset=reserved";
aeron.addSubscription(ch, streamId);
aeron.addSubscription(ch, streamId); Defensive patterns
Strategy: validation
Validate before calling
ChannelUri uri = ChannelUri.parse(channel);
String offset = uri.get(CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME); // must match the existing subscription's value on the receive endpoint
if (existingOffset != null && !Objects.equals(existingOffset, offset))
{
throw new IllegalArgumentException("channel-receive-timestamp-offset conflicts with existing subscription");
} Try / catch
try
{
aeron.addSubscription(channel, streamId);
}
catch (InvalidChannelException ex)
{
if (ex.getMessage().contains(CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME))
{
log.error("Receive timestamp offset conflicts with an existing subscription on this channel");
}
} Prevention
- Use one shared channel-URI factory for all subscriptions to a given endpoint
- Set channel-receive-timestamp-offset explicitly on every URI for the channel
- Check Aeron version release notes for default changes to timestamp offset options before upgrading
When it happens
Trigger: Adding a subscription on the same UDP receive channel (e.g. same multicast group/endpoint) with a different channel-receive-timestamp-offset value than the endpoint's existing subscription; omitting the param when the first subscription set it (or vice versa).
Common situations: Mixed configuration across components in the same JVM subscribing to the same multicast feed; default changes between Aeron versions causing old and new channel strings to disagree; manual per-subscription timestamp tuning.
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
- option conflicts with existing subscription: reliable=
- option conflicts with existing subscription: rejoin=
- option conflicts with existing subscription: isResponse=
- Aeron client instance must set…
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/fbc52dc5586545f6.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java:1537
final UdpChannel udpChannel, final SendChannelEndpoint channelEndpoint)
{
if (udpChannel.channelSendTimestampOffset() != channelEndpoint.udpChannel().channelSendTimestampOffset())
{
throw new InvalidChannelException(
"option conflicts with existing subscription: " + CHANNEL_SEND_TIMESTAMP_OFFSET_PARAM_NAME + "=" +
udpChannel.channelSendTimestampOffset() +
" existingChannel=" + channelEndpoint.originalUriString() + " channel=" +
udpChannel.originalUriString());
}
}
private static void validateReceiveTimestampOffset(
final UdpChannel udpChannel, final ReceiveChannelEndpoint channelEndpoint)
{
if (udpChannel.channelReceiveTimestampOffset() !=
channelEndpoint.subscriptionUdpChannel().channelReceiveTimestampOffset())
{
throw new InvalidChannelException(
"option conflicts with existing subscription: " + CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME + "=" +
udpChannel.channelReceiveTimestampOffset() +
" existingChannel=" + channelEndpoint.originalUriString() + " channel=" +
udpChannel.originalUriString());
}
}
private SendChannelEndpoint findExistingManualSendChannelEndpoint(final long registrationId)
{
SendChannelEndpoint sendChannelEndpoint = null;
for (final NetworkPublication publication : networkPublications)
{
if (registrationId == publication.registrationId())
{
sendChannelEndpoint = publication.channelEndpoint();
break;
}View on GitHub (pinned to 6d60124e15)