{"record":{"id":"fbc52dc5586545f6","repo":"aeron-io/aeron","slug":"option-conflicts-with-existing-subscription-channel-receive","errorCode":null,"errorMessage":"option conflicts with existing subscription: ${CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME}=${offset} existingChannel=${existingChannel} channel=${channel}","messagePattern":"option conflicts with existing subscription: (.+?)=(.+?) existingChannel=(.+?) channel=(.+?)","errorType":"exception","errorClass":"InvalidChannelException","httpStatus":null,"severity":"error","filePath":"aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java","lineNumber":1537,"sourceCode":"        final UdpChannel udpChannel, final SendChannelEndpoint channelEndpoint)\n    {\n        if (udpChannel.channelSendTimestampOffset() != channelEndpoint.udpChannel().channelSendTimestampOffset())\n        {\n            throw new InvalidChannelException(\n                \"option conflicts with existing subscription: \" + CHANNEL_SEND_TIMESTAMP_OFFSET_PARAM_NAME + \"=\" +\n                    udpChannel.channelSendTimestampOffset() +\n                    \" existingChannel=\" + channelEndpoint.originalUriString() + \" channel=\" +\n                    udpChannel.originalUriString());\n        }\n    }\n\n    private static void validateReceiveTimestampOffset(\n        final UdpChannel udpChannel, final ReceiveChannelEndpoint channelEndpoint)\n    {\n        if (udpChannel.channelReceiveTimestampOffset() !=\n            channelEndpoint.subscriptionUdpChannel().channelReceiveTimestampOffset())\n        {\n            throw new InvalidChannelException(\n                \"option conflicts with existing subscription: \" + CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME + \"=\" +\n                    udpChannel.channelReceiveTimestampOffset() +\n                    \" existingChannel=\" + channelEndpoint.originalUriString() + \" channel=\" +\n                    udpChannel.originalUriString());\n        }\n    }\n\n    private SendChannelEndpoint findExistingManualSendChannelEndpoint(final long registrationId)\n    {\n        SendChannelEndpoint sendChannelEndpoint = null;\n\n        for (final NetworkPublication publication : networkPublications)\n        {\n            if (registrationId == publication.registrationId())\n            {\n                sendChannelEndpoint = publication.channelEndpoint();\n                break;\n            }","sourceCodeStart":1519,"sourceCodeEnd":1555,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java#L1519-L1555","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\naeron.addSubscription(\"aeron:udp?endpoint=224.0.1.1:40456|channel-receive-timestamp-offset=reserved\", streamId);\naeron.addSubscription(\"aeron:udp?endpoint=224.0.1.1:40456\", streamId); // mismatch -> InvalidChannelException\n// after\nString ch = \"aeron:udp?endpoint=224.0.1.1:40456|channel-receive-timestamp-offset=reserved\";\naeron.addSubscription(ch, streamId);\naeron.addSubscription(ch, streamId);","handlingStrategy":"validation","validationCode":"ChannelUri uri = ChannelUri.parse(channel);\nString offset = uri.get(CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME); // must match the existing subscription's value on the receive endpoint\nif (existingOffset != null && !Objects.equals(existingOffset, offset))\n{\n    throw new IllegalArgumentException(\"channel-receive-timestamp-offset conflicts with existing subscription\");\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    aeron.addSubscription(channel, streamId);\n}\ncatch (InvalidChannelException ex)\n{\n    if (ex.getMessage().contains(CHANNEL_RECEIVE_TIMESTAMP_OFFSET_PARAM_NAME))\n    {\n        log.error(\"Receive timestamp offset conflicts with an existing subscription on this channel\");\n    }\n}","preventionTips":["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"],"tags":["aeron","configuration","subscription","conflict"],"backgroundTag":"conflicting-config-options","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}