aeron-io/aeron · error · IllegalArgumentException

'control-mode=dynamic' requires that 'control' parameter is…

Error message

'control-mode=dynamic' requires that 'control' parameter is set, channel={channel}

What it means

When a publication URI specifies an explicit 'control' address but neither an 'endpoint' nor a 'control-mode', the driver cannot tell whether this is dynamic MDC or manual control, so it rejects the channel with this IllegalArgumentException. Specifying control alone is ambiguous and therefore invalid.

Solutions

  1. Add control-mode=dynamic (or manual) to the URI when control is specified
  2. Or add endpoint=host:port if a unicast publication with explicit control response was intended
  3. Remove the control parameter if a plain endpoint-based publication was intended

Example fix

// before
aeron.addPublication("aeron:udp?control=localhost:40456", 1001);
// after
aeron.addPublication("aeron:udp?control=localhost:40456|control-mode=dynamic", 1001);
Defensive patterns

Strategy: validation

Validate before calling

if (uriParam(channel, "control", null) != null && uriParam(channel, "endpoint", null) == null
    && uriParam(channel, "control-mode", null) == null) {
    throw new IllegalArgumentException("control= requires endpoint= or control-mode=: " + channel);
}

Try / catch

try { aeron.addPublication(channel, streamId); } catch (IllegalArgumentException e) { if (e.getMessage().contains("'control' parameter requires")) { log.error("specify control-mode or endpoint for {}", channel); } throw e; }

Prevention

When it happens

Trigger: addPublication with "aeron:udp?control=localhost:40456" and no endpoint and no control-mode parameter; migrating from an MDC URI by deleting control-mode but keeping control.

Common situations: URI trimming/refactoring removed control-mode=dynamic while control remained; hand-written URIs omitting control-mode assuming it is implied by control.

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


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/da105ce6fa33f26f. Report an issue: GitHub.

Appendix: source

Thrown at aeron-driver/src/main/java/io/aeron/driver/DriverConductor.java:2345

        {
            throw new IllegalArgumentException(
                ENDPOINT_PARAM_NAME + " has port=0 for publication: channel=" + udpChannel.originalUriString());
        }
    }

    private static void validateControlForPublication(final UdpChannel udpChannel)
    {
        if (udpChannel.isDynamicControlMode() && !udpChannel.hasExplicitControl())
        {
            throw new IllegalArgumentException(
                "'control-mode=dynamic' requires that 'control' parameter is set, channel=" +
                    udpChannel.originalUriString());
        }

        if (udpChannel.hasExplicitControl() && !udpChannel.hasExplicitEndpoint() &&
            ControlMode.NONE == udpChannel.controlMode())
        {
            throw new IllegalArgumentException(
                "'control' parameter requires that either 'endpoint' or 'control-mode' is specified, channel=" +
                    udpChannel.originalUriString());
        }
    }

    private static void validateControlForSubscription(final UdpChannel udpChannel)
    {
        if (udpChannel.hasExplicitControl() &&
            0 == udpChannel.localControl().getPort())
        {
            throw new IllegalArgumentException(MDC_CONTROL_PARAM_NAME + " has port=0 for subscription: channel=" +
                udpChannel.originalUriString());
        }
    }

    private static void validateTimestampConfiguration(final UdpChannel udpChannel)
    {
        if (null != udpChannel.channelUri().get(MEDIA_RCV_TIMESTAMP_OFFSET_PARAM_NAME))

View on GitHub (pinned to 6d60124e15)