{"record":{"id":"354a0d5166f8b653","repo":"aeron-io/aeron","slug":"uri-must-have-explicit-control-endpoint-or-be-manual-control","errorCode":null,"errorMessage":"URI must have explicit control, endpoint, or be manual control-mode when original: channel=${originalUriString}","messagePattern":"URI must have explicit control, endpoint, or be manual control-mode when original: channel=(.+?)","errorType":"exception","errorClass":"InvalidChannelException","httpStatus":null,"severity":"error","filePath":"aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java","lineNumber":1585,"sourceCode":"        return sendChannelEndpoint;\n    }\n\n    private SendChannelEndpoint findExistingSendChannelEndpoint(final UdpChannel udpChannel)\n    {\n        if (udpChannel.hasTag())\n        {\n            for (final SendChannelEndpoint endpoint : sendChannelEndpointByChannelMap.values())\n            {\n                if (endpoint.matchesTag(udpChannel))\n                {\n                    return endpoint;\n                }\n            }\n\n            if (!udpChannel.hasExplicitControl() && !udpChannel.isManualControlMode() &&\n                !udpChannel.channelUri().containsKey(ENDPOINT_PARAM_NAME))\n            {\n                throw new InvalidChannelException(\n                    \"URI must have explicit control, endpoint, or be manual control-mode when original: channel=\" +\n                        udpChannel.originalUriString());\n            }\n        }\n\n        SendChannelEndpoint endpoint = sendChannelEndpointByChannelMap.get(udpChannel.canonicalForm());\n        if (null != endpoint && endpoint.udpChannel().hasTag() && udpChannel.hasTag() &&\n            endpoint.udpChannel().tag() != udpChannel.tag())\n        {\n            endpoint = null;\n        }\n\n        if (null != endpoint)\n        {\n            throwResourceTemporaryUnavailableIfEndpointIsClosing(endpoint);\n        }\n\n        return endpoint;","sourceCodeStart":1567,"sourceCodeEnd":1603,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java#L1567-L1603","documentation":"Aeron requires a UDP publication channel URI to be addressable: it must specify an explicit 'control' address, an 'endpoint' address, or declare 'control-mode=manual'. This InvalidChannelException is thrown during publication creation in the driver when the parsed UdpChannel satisfies none of these, because otherwise destinations could never be resolved.","triggerScenarios":"Calling Aeron.addPublication/addExclusivePublication with a URI like \"aeron:udp?term-length=64k\" (no endpoint, no control, no manual control-mode), or an MDC publication where the original channel fails the re-validation (e.g. sparse/URI with session-id but no addressing params).","commonSituations":"Typo in parameter name (endpooint vs endpoint); assuming defaults provide an endpoint; building URIs programmatically and dropping the endpoint parameter; migrating a subscription-style URI to a publication.","solutions":["Add endpoint=host:port to the channel URI for unicast publication","Add control=host:port (typically with control-mode=dynamic) for MDC publication","Add control-mode=manual for manual multi-destination control","Fix the parameter spelling/URI construction so one of the three required options is present"],"exampleFix":"// before\nAeron.addPublication(\"aeron:udp?term-length=64k\", 1001);\n// after\nAeron.addPublication(\"aeron:udp?endpoint=localhost:40456|term-length=64k\", 1001);","handlingStrategy":"validation","validationCode":"UriPublication pub = UriPublication.parse(channel);\nboolean valid = pub.hasControl() || pub.hasEndpoint() || \"manual\".equals(pub.get(\"control-mode\"));\nif (!valid) throw new IllegalArgumentException(\"publication URI needs endpoint, control, or control-mode=manual: \" + channel);","typeGuard":null,"tryCatchPattern":"try { aeron.addPublication(channel, streamId); } catch (InvalidChannelException e) { log.error(\"channel URI not addressable: {}\", e.getMessage()); throw new ConfigException(channel); }","preventionTips":["Include endpoint= in every unicast publication URI","Always pair control= with control-mode=dynamic for MDC","Lint channel URIs in a startup check before adding publications","Keep a single URI-builder utility with required-param assertions"],"tags":["aeron","uri","channel-config","mdc"],"backgroundTag":"missing-required-config-field","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"}