aeron-io/aeron · error · InvalidChannelException

option conflicts with existing subscription

Error message

option conflicts with existing subscription: ${CHANNEL_SEND_TIMESTAMP_OFFSET_PARAM_NAME}=${offset} existingChannel=${existingChannel} channel=${channel}

What it means

When a new subscription reuses an existing SendChannelEndpoint (same channel), the driver requires the channel-send-timestamp-offset option to match exactly what the existing endpoint was created with. A mismatch would make timestamps inconsistent across subscriptions sharing the endpoint, so the driver throws InvalidChannelException naming both the existing channel URI and the new one.

Solutions

  1. Make all subscriptions on the same channel use the identical channel-send-timestamp-offset param value
  2. Set the option explicitly on every channel string rather than relying on defaults so all agree
  3. Use distinct channels/endpoints if different timestamp behavior per subscription is truly required
  4. Audit all channel strings deployed in the process for the conflicting parameter

Example fix

// before
aeron.addSubscription("aeron:udp?endpoint=224.0.1.1:40456", streamId); // offset default
aeron.addSubscription("aeron:udp?endpoint=224.0.1.1:40456|channel-send-timestamp-offset=0", streamId); // conflicts
// after
String ch = "aeron:udp?endpoint=224.0.1.1:40456|channel-send-timestamp-offset=0";
aeron.addSubscription(ch, streamId);
aeron.addSubscription(ch, streamId); // identical options
Defensive patterns

Strategy: validation

Validate before calling

ChannelUri uri = ChannelUri.parse(channel);
String offset = uri.get(CHANNEL_SEND_TIMESTAMP_OFFSET_PARAM_NAME); // compare with the value used by existing subscriptions on this endpoint
if (existingOffset != null && !Objects.equals(existingOffset, offset))
{
    throw new IllegalArgumentException("channel-send-timestamp-offset conflicts with existing subscription");
}

Try / catch

try
{
    aeron.addSubscription(channel, streamId);
}
catch (InvalidChannelException ex)
{
    if (ex.getMessage().contains(CHANNEL_SEND_TIMESTAMP_OFFSET_PARAM_NAME))
    {
        log.error("Timestamp offset option conflicts with an existing subscription on this channel");
    }
}

Prevention

When it happens

Trigger: Adding a second subscription on the same UDP channel URI but with a different channel-send-timestamp-offset param value (or one with the option and one without, given differing defaults) than the existing subscription's endpoint.

Common situations: Two services/libraries in one process subscribing to the same channel but configured independently (one sets timestamps offset to media driver default, the other leaves it unset); config drift after upgrading where defaults changed; copying channel strings between environments.

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/43ada0948b79ab74. Report an issue: GitHub.

Appendix: source

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

            SOCKET_RCVBUF_PARAM_NAME,
            udpChannel.socketRcvbufLength(),
            channelEndpoint.socketRcvbufLength(),
            udpChannel.originalUriString(),
            channelEndpoint.originalUriString());
        validateChannelBufferLength(
            SOCKET_SNDBUF_PARAM_NAME,
            udpChannel.socketSndbufLength(),
            channelEndpoint.socketSndbufLength(),
            udpChannel.originalUriString(),
            channelEndpoint.originalUriString());
    }

    private static void validateChannelSendTimestampOffset(
        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());

View on GitHub (pinned to 6d60124e15)