aeron-io/aeron · error · IllegalArgumentException
invalid control mode
Error message
invalid control mode: ${controlMode} What it means
Thrown by ChannelUriStringBuilder.controlMode(String) when the control mode is not one of the allowed values: manual, dynamic, or response. The control mode tells the driver how multicast control messages are managed, so unknown values are rejected at build time.
Solutions
- Use ChannelUriStringBuilder.MDC_CONTROL_MODE_MANUAL ("manual").
- Use ChannelUriStringBuilder.MDC_CONTROL_MODE_DYNAMIC ("dynamic").
- Use CONTROL_MODE_RESPONSE ("response") if response channels are intended; otherwise omit controlMode.
Example fix
// before
builder.controlMode("static");
// after
builder.controlMode(ChannelUriStringBuilder.MDC_CONTROL_MODE_MANUAL); Defensive patterns
Strategy: validation
Validate before calling
Set<String> OK = Set.of(ChannelUriStringBuilder.MDC_CONTROL_MODE_MANUAL, ChannelUriStringBuilder.MDC_CONTROL_MODE_DYNAMIC, ChannelUriStringBuilder.CONTROL_MODE_RESPONSE);
if (mode != null && !OK.contains(mode)) { throw new IllegalArgumentException("invalid control mode: " + mode); } Type guard
boolean isValidControlMode(String m) { return m == null || ChannelUriStringBuilder.MDC_CONTROL_MODE_MANUAL.equals(m) || ChannelUriStringBuilder.MDC_CONTROL_MODE_DYNAMIC.equals(m) || ChannelUriStringBuilder.CONTROL_MODE_RESPONSE.equals(m); } Try / catch
try { builder.controlMode(m); } catch (IllegalArgumentException e) { builder.controlMode(ChannelUriStringBuilder.MDC_CONTROL_MODE_MANUAL); } Prevention
- Use the builder's public constants, not literals
- Validate an enum in your config layer before mapping to the string
- Lowercase/trim user input before setting
When it happens
Trigger: builder.controlMode("static"), builder.controlMode("manual-dynamic"), or a config string that isn't exactly MDC_CONTROL_MODE_MANUAL / MDC_CONTROL_MODE_DYNAMIC / CONTROL_MODE_RESPONSE.
Common situations: Guessing mode names ("auto", "static"); case mismatch ("MANUAL"); upgrading from older Aeron versions where only manual/dynamic existed and using a stale constant.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- difference greater than 2^31 - 1: termId=
- termOffset= > termLength=
- segment file length not a power of 2
- segment file length not in valid range
- AeronArchive.Context.messageRetryAttempts must be > 0, got:
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/916e6d9394fc31c9.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java:460
* Set the control mode for multi-destination-cast. Set to "manual" for allowing control from the publication API.
*
* @param controlMode for taking control of MDC.
* @return this for a fluent API.
* @see Publication#addDestination(String)
* @see Publication#removeDestination(String)
* @see CommonContext#MDC_CONTROL_MODE_PARAM_NAME
* @see CommonContext#MDC_CONTROL_MODE_MANUAL
* @see CommonContext#MDC_CONTROL_MODE_DYNAMIC
* @see CommonContext#CONTROL_MODE_RESPONSE
*/
public ChannelUriStringBuilder controlMode(final String controlMode)
{
if (null != controlMode &&
!controlMode.equals(MDC_CONTROL_MODE_MANUAL) &&
!controlMode.equals(MDC_CONTROL_MODE_DYNAMIC) &&
!controlMode.equals(CONTROL_MODE_RESPONSE))
{
throw new IllegalArgumentException("invalid control mode: " + controlMode);
}
this.controlMode = controlMode;
return this;
}
/**
* Set the control mode to be what is in the {@link ChannelUri} which may be null.
*
* @param channelUri to read the value from.
* @return this for a fluent API.
* @see CommonContext#MDC_CONTROL_MODE_PARAM_NAME
*/
public ChannelUriStringBuilder controlMode(final ChannelUri channelUri)
{
return controlMode(channelUri.get(MDC_CONTROL_MODE_PARAM_NAME));
}
View on GitHub (pinned to 6d60124e15)