aeron-io/aeron · error · IllegalArgumentException
explicit control expected with dynamic control mode:
Error message
explicit control expected with dynamic control mode:
What it means
UdpChannel.parse throws IllegalArgumentException when a channel URI sets control-mode=dynamic but provides no explicit control address. Dynamic multi-destination-cast requires a known control address for the receiver(s) to contact, so an explicitly configured control is mandatory in that mode.
Solutions
- Add an explicit control address to the URI, e.g. aeron:udp?control-mode=dynamic|control=224.0.1.1:40456
- Confirm the parameter name is exactly 'control' and the value parses as address:port (or [v6]:port)
- If destinations are added manually at runtime, use control-mode=manual instead of dynamic
Example fix
// before "aeron:udp?control-mode=dynamic" // after "aeron:udp?control-mode=dynamic|control=224.0.1.1:40456"
Defensive patterns
Strategy: validation
Validate before calling
boolean isDynamic = "dynamic".equals(params.get("control-mode"));
boolean hasControl = params.containsKey("control") && !params.get("control").isEmpty();
if (isDynamic && !hasControl) throw new IllegalArgumentException("control-mode=dynamic requires control=<address:port>"); Try / catch
try {
UdpChannel.parse(uri, true, NameResolver.NULL_NAME_RESOLVER);
} catch (IllegalArgumentException e) {
// reject/mend URI before configuring driver
} Prevention
- Always pair control-mode=dynamic with an explicit control address
- Centralize URI building and assert invariants there
- Beware typos: unknown parameters are silently ignored
When it happens
Trigger: Parsing a URI such as aeron:udp?control-mode=dynamic (with no control= parameter) when creating a publication or subscription via Aeron.addPublication/addSubscription.
Common situations: MDC setups where the control= parameter was dropped or misspelled (e.g. control-adress typo); confusing control-mode with manual mode; partially edited URIs when switching from manual to dynamic mode.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Unable to derive…
- invalid channel
- URI must have explicit control, endpoint, or be manual…
- 'control-mode=dynamic' requires that 'control' parameter is…
- 'control-mode=dynamic' requires that 'control' parameter is…
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/f2a7195c092564d2.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/media/UdpChannel.java:168
final String tagIdStr = channelUri.channelTag();
final ControlMode controlMode = parseControlMode(channelUri);
final int socketRcvbufLength = parseBufferLength(channelUri, SOCKET_RCVBUF_PARAM_NAME);
final int socketSndbufLength = parseBufferLength(channelUri, SOCKET_SNDBUF_PARAM_NAME);
final int receiverWindowLength = parseBufferLength(
channelUri, RECEIVER_WINDOW_LENGTH_PARAM_NAME);
final boolean requiresAdditionalSuffix = !isDestination &&
(null == endpointAddress && null == controlAddress ||
(null != endpointAddress && endpointAddress.getPort() == 0) ||
(null != controlAddress && controlAddress.getPort() == 0));
final boolean hasNoDistinguishingCharacteristic =
null == endpointAddress && null == controlAddress && null == tagIdStr;
if (ControlMode.DYNAMIC == controlMode && null == controlAddress)
{
throw new IllegalArgumentException(
"explicit control expected with dynamic control mode: " + channelUriString);
}
if (hasNoDistinguishingCharacteristic && ControlMode.MANUAL != controlMode &&
ControlMode.RESPONSE != controlMode)
{
throw new IllegalArgumentException(
"URIs for UDP must specify an endpoint, control, tags, or control-mode=manual/response: " +
channelUriString);
}
if (null != endpointAddress && endpointAddress.isUnresolved())
{
throw new UnknownHostException("could not resolve endpoint address: " + endpointAddress);
}
if (null != controlAddress && controlAddress.isUnresolved())
{View on GitHub (pinned to 6d60124e15)