{"record":{"id":"43ada0948b79ab74","repo":"aeron-io/aeron","slug":"option-conflicts-with-existing-subscription-channel-send","errorCode":null,"errorMessage":"option conflicts with existing subscription: ${CHANNEL_SEND_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":1523,"sourceCode":"            SOCKET_RCVBUF_PARAM_NAME,\n            udpChannel.socketRcvbufLength(),\n            channelEndpoint.socketRcvbufLength(),\n            udpChannel.originalUriString(),\n            channelEndpoint.originalUriString());\n        validateChannelBufferLength(\n            SOCKET_SNDBUF_PARAM_NAME,\n            udpChannel.socketSndbufLength(),\n            channelEndpoint.socketSndbufLength(),\n            udpChannel.originalUriString(),\n            channelEndpoint.originalUriString());\n    }\n\n    private static void validateChannelSendTimestampOffset(\n        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());","sourceCodeStart":1505,"sourceCodeEnd":1541,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java#L1505-L1541","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make all subscriptions on the same channel use the identical channel-send-timestamp-offset param value","Set the option explicitly on every channel string rather than relying on defaults so all agree","Use distinct channels/endpoints if different timestamp behavior per subscription is truly required","Audit all channel strings deployed in the process for the conflicting parameter"],"exampleFix":"// before\naeron.addSubscription(\"aeron:udp?endpoint=224.0.1.1:40456\", streamId); // offset default\naeron.addSubscription(\"aeron:udp?endpoint=224.0.1.1:40456|channel-send-timestamp-offset=0\", streamId); // conflicts\n// after\nString ch = \"aeron:udp?endpoint=224.0.1.1:40456|channel-send-timestamp-offset=0\";\naeron.addSubscription(ch, streamId);\naeron.addSubscription(ch, streamId); // identical options","handlingStrategy":"validation","validationCode":"ChannelUri uri = ChannelUri.parse(channel);\nString offset = uri.get(CHANNEL_SEND_TIMESTAMP_OFFSET_PARAM_NAME); // compare with the value used by existing subscriptions on this endpoint\nif (existingOffset != null && !Objects.equals(existingOffset, offset))\n{\n    throw new IllegalArgumentException(\"channel-send-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_SEND_TIMESTAMP_OFFSET_PARAM_NAME))\n    {\n        log.error(\"Timestamp offset option conflicts with an existing subscription on this channel\");\n    }\n}","preventionTips":["Centralize channel URI construction so all subscriptions on a channel share identical params","Never rely on default option values when sharing channels; set options explicitly","Document required channel params for all in-process components sharing a driver"],"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"}