aeron-io/aeron · error · ControlProtocolException

INVALID_CHANNEL

INVALID_CHANNEL

Error message

channel does not allow manual control

What it means

Aeron throws ControlProtocolException(ErrorCode.INVALID_CHANNEL) when a manual (MDC) control operation such as adding/removing destinations is requested on a receive channel endpoint that is not configured as a multi-destination (no MultiRcvDestination). Only channels created with control-mode=manual support dynamic destination control.

Solutions

  1. Create the subscription channel with control-mode=manual in the URI, e.g. aeron:udp?control-mode=manual
  2. Restructure code so destination add/remove calls are only made on subscriptions created for manual multi-destination control
  3. Catch ControlProtocolException and check getErrorCode() == ErrorCode.INVALID_CHANNEL to surface the misconfigured channel

Example fix

// before
Subscription sub = aeron.addSubscription("aeron:udp?endpoint=127.0.0.1:40456", 1001);
sub.addDestination("aeron:udp?endpoint=127.0.0.1:40457"); // throws
// after
Subscription sub = aeron.addSubscription("aeron:udp?control-mode=manual", 1001);
sub.addDestination("aeron:udp?endpoint=127.0.0.1:40457");
Defensive patterns

Strategy: try-catch

Validate before calling

boolean manual = uri.contains("control-mode=manual");
if (!manual) throw new IllegalStateException("receive channel must use control-mode=manual for addDestination");

Try / catch

try {
    subscription.addDestination(dstUri);
} catch (ControlProtocolException e) {
    if (e.errorCode() == ErrorCode.INVALID_CHANNEL) { /* recreate subscription with control-mode=manual */ }
}

Prevention

When it happens

Trigger: Driver command ADD_RCV_DESTINATION/REMOVE_RCV_DESTINATION arrives for a subscription whose ReceiveChannelEndpoint was created from a plain (non-manual) URI, so validateAllowsDestinationControl finds multiRcvDestination == null.

Common situations: Calling Subscription.addDestination (or driver client addRcvDestination) on a subscription created from a normal aeron:udp?endpoint=... URI instead of one with control-mode=manual; mixing manual and non-manual channels in MDC setups.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at aeron-driver/src/main/java/io/aeron/driver/media/ReceiveChannelEndpoint.java:505

     * Has the channel got control of destinations for MDS.
     *
     * @return true if the channel got control of destinations for MDS.
     */
    public boolean hasDestinationControl()
    {
        return null != multiRcvDestination;
    }

    /**
     * Validate that the channel allows destination control.
     * <p>
     * If not then a {@link ControlProtocolException} will be thrown.
     */
    public void validateAllowsDestinationControl()
    {
        if (null == multiRcvDestination)
        {
            throw new ControlProtocolException(ErrorCode.INVALID_CHANNEL, "channel does not allow manual control");
        }
    }

    /**
     * Is the primary transport multicast?
     *
     * @return true if the primary transport is multicast.
     */
    public boolean isMulticast()
    {
        return isMulticast(0);
    }

    /**
     * Is a given transport index multicast?
     *
     * @param transportIndex to check for multicast.
     * @return true if the transport index is multicast.

View on GitHub (pinned to 6d60124e15)