{"record":{"id":"24edafa7501f4378","repo":"aeron-io/aeron","slug":"egresschannel-must-be-specified","errorCode":null,"errorMessage":"egressChannel must be specified","messagePattern":"egressChannel must be specified","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"aeron-cluster/src/main/java/io/aeron/cluster/client/AeronCluster.java","lineNumber":1494,"sourceCode":"            }\n\n            if (Strings.isEmpty(ingressChannel))\n            {\n                throw new ConfigurationException(\"ingressChannel must be specified\");\n            }\n\n            if (ingressChannel.startsWith(CommonContext.IPC_CHANNEL))\n            {\n                if (null != ingressEndpoints)\n                {\n                    throw new ConfigurationException(\n                        \"AeronCluster.Context ingressEndpoints must be null when using IPC ingress\");\n                }\n            }\n\n            if (Strings.isEmpty(egressChannel))\n            {\n                throw new ConfigurationException(\"egressChannel must be specified\");\n            }\n\n            final ChannelUri egressChannelUri = ChannelUri.parse(egressChannel);\n            if (egressChannelUri.isUdp())\n            {\n                egressChannelUri.put(REJOIN_PARAM_NAME, \"false\");\n                egressChannel = egressChannelUri.toString();\n            }\n\n            if (clientName.length() > Aeron.Configuration.MAX_CLIENT_NAME_LENGTH)\n            {\n                throw new ConfigurationException(\n                    \"AeronCluster.Context.clientName length must be <= \" + Aeron.Configuration.MAX_CLIENT_NAME_LENGTH);\n            }\n\n            if (null == aeron)\n            {\n                aeron = Aeron.connect(","sourceCodeStart":1476,"sourceCodeEnd":1512,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-cluster/src/main/java/io/aeron/cluster/client/AeronCluster.java#L1476-L1512","documentation":"AeronCluster requires an egress channel so the cluster can send responses back to the client. Context.conclude() throws ConfigurationException when egressChannel is null or empty; the channel must be a valid URI (typically aeron:udp?endpoint=<client>:<port>).","triggerScenarios":"Calling AeronCluster.connect() or ctx.conclude() without calling ctx.egressChannel(...), or setting it to an empty string.","commonSituations":"Copying only the ingress half of a sample config; refactoring Context setup and dropping the egress line; env-driven config where the egress property is absent.","solutions":["Set ctx.egressChannel(\"aeron:udp?endpoint=<host>:<port>\") before connect()","For a wildcard local port use e.g. aeron:udp?endpoint=localhost:0","Verify your config loader actually populates egressChannel (log it before connect)"],"exampleFix":"// before\nnew AeronCluster.Context().ingressChannel(\"aeron:udp?endpoint=localhost:20000\");\n// after\nnew AeronCluster.Context()\n    .ingressChannel(\"aeron:udp?endpoint=localhost:20000\")\n    .egressChannel(\"aeron:udp?endpoint=localhost:0\");","handlingStrategy":"validation","validationCode":"if (ctx.egressChannel() == null || ctx.egressChannel().isEmpty()) {\n    throw new IllegalArgumentException(\"egressChannel must be set before AeronCluster.connect()\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep ingress/egress channel setup together in one factory method","Log the final channel URIs at startup to catch missing config early"],"tags":["configuration","cluster-client","validation"],"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-19T12:17:13.211Z"}