aeron-io/aeron · error · InvalidChannelException

option conflicts with existing subscription: reliable=

Error message

option conflicts with existing subscription: reliable=${isReliable} existingChannel=${existingChannel} channel=${channel}

What it means

Within a single Aeron client, all subscriptions sharing a channel endpoint and streamId must agree on the 'reliable' option. The driver throws this InvalidChannelException when a new addSubscription matches an existing subscription on channel/stream/tag but declares a different reliable value.

Solutions

  1. Align the reliable parameter across all addSubscription calls for the same channel/streamId
  2. Remove or close the conflicting existing subscription first
  3. Use a different streamId or session-id range if different reliability semantics are genuinely needed
  4. Centralize channel URI construction so all subscribers share one config source

Example fix

// before
aeron.addSubscription("aeron:udp?endpoint=localhost:40456|reliable=false", 1001);
// after (match existing subscription)
aeron.addSubscription("aeron:udp?endpoint=localhost:40456|reliable=true", 1001);
Defensive patterns

Strategy: try-catch

Validate before calling

boolean reliable = Boolean.parseBoolean(uriParam(channel, "reliable", "true"));
// assert reliable matches the value used by all other subscribers of this channel/streamId

Try / catch

try { aeron.addSubscription(channel, streamId, handler, unavailableHandler); } catch (InvalidChannelException e) { if (e.getMessage().contains("option conflicts")) { log.error("align reliable option with existing subscription: {}", e.getMessage()); } throw e; }

Prevention

When it happens

Trigger: Calling Aeron.addSubscription with reliable=false (or true) on a URI/streamId where a subscription with the opposite reliable setting already exists and matches the same endpoint, stream, and tag.

Common situations: Two parts of an application independently subscribing to the same channel/stream with divergent reliability config; a shared library component adds subscriptions with its own defaults; copying URIs between services with different ?reliable= values.

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


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/a19f4d7a282ce8ac. Report an issue: GitHub.

Appendix: source

Thrown at aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java:1622

    }

    private void checkForClashingSubscription(
        final SubscriptionParams params, final UdpChannel udpChannel, final int streamId)
    {
        final ReceiveChannelEndpoint channelEndpoint = findExistingReceiveChannelEndpoint(udpChannel);
        if (null != channelEndpoint)
        {
            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=" +

View on GitHub (pinned to 6d60124e15)