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 control operation (add/remove destination) is performed on a send channel endpoint whose multiSndDestination is not a ManualSndMultiDestination. Only publication channels created with control-mode=manual allow dynamic destination management.
Solutions
- Create the publication channel URI with control-mode=manual, e.g. aeron:udp?control-mode=manual
- Ensure all publications on the same channel/stream use consistent control mode so endpoint lookup finds a manual-capable endpoint
- Catch ControlProtocolException and inspect getErrorCode() == ErrorCode.INVALID_CHANNEL to detect the misconfiguration
Example fix
// before
Publication pub = aeron.addPublication("aeron:udp?endpoint=224.0.1.1:40456", 1001);
pub.addDestination("aeron:udp?endpoint=10.0.0.1:40456"); // throws
// after
Publication pub = aeron.addPublication("aeron:udp?control-mode=manual", 1001);
pub.addDestination("aeron:udp?endpoint=10.0.0.1:40456"); Defensive patterns
Strategy: try-catch
Validate before calling
boolean manual = uri.contains("control-mode=manual");
if (!manual) throw new IllegalStateException("send channel must use control-mode=manual for addDestination"); Try / catch
try {
publication.addDestination(dstUri);
} catch (ControlProtocolException e) {
if (e.errorCode() == ErrorCode.INVALID_CHANNEL) { /* recreate publication with control-mode=manual */ }
} Prevention
- Create MDC publications with control-mode=manual in the URI
- Keep control mode consistent across all publications on the same channel so endpoint reuse succeeds
- Guard destination add/remove calls behind a check that the publication was created in manual mode
When it happens
Trigger: validateAllowsManualControl is invoked from findExistingManualSendChannelEndpoint when reusing/looking up a send channel for a manual-control request, and the existing endpoint was created from a URI without control-mode=manual.
Common situations: Calling Publication.addDestination/removeDestination on a publication created from a normal aeron:udp?endpoint=... URI; an existing publication on the same stream/URI was created without manual mode so the endpoint reuse fails; MDC publishing configured incorrectly.
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
- INVALID_CHANNEL
- explicit control expected with dynamic control mode:
- URIs for UDP must specify an endpoint, control, tags, or…
- Aeron client instance must set…
- Aeron client must use a RethrowingErrorHandler
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/7782f8b132bf1f88.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/media/SendChannelEndpoint.java:570
{
final long responseCorrelationId = publication.responseCorrelationId();
if (Aeron.NULL_VALUE != responseCorrelationId)
{
conductorProxy.responseSetup(responseCorrelationId, msg.responseSessionId());
}
}
}
/**
* Validate that the channel allows manual control for destinations.
* <p>
* If not then a {@link ControlProtocolException} will be thrown.
*/
public void validateAllowsManualControl()
{
if (!(multiSndDestination instanceof ManualSndMultiDestination))
{
throw new ControlProtocolException(ErrorCode.INVALID_CHANNEL, "channel does not allow manual control");
}
}
/**
* Add a destination for an MDC channel.
*
* @param channelUri for the destination to be added.
* @param address of the destination to be added.
* @param registrationId of the destination.
*/
public void addDestination(final ChannelUri channelUri, final InetSocketAddress address, final long registrationId)
{
multiSndDestination.addDestination(channelUri, address, registrationId);
}
/**
* Remove a destination from an MDC channel.
*View on GitHub (pinned to 6d60124e15)