aeron-io/aeron · error · IllegalArgumentException
matching tag= has mismatched control-mode: <>
Error message
matching tag= has mismatched control-mode: <>
What it means
Thrown by UdpChannel.isEquivalentTo when two channel URIs sharing the same matching tag declare different control-mode values. Tagged channels that are expected to alias the same transport must agree on control-mode.
Solutions
- Make control-mode identical for all URIs sharing the same tag
- Use distinct tags for channels with different control modes
- Remove the matching tag if the channels are intentionally different
Example fix
// before "aeron:udp?tags=1001|control-mode=manual|control=..." and "aeron:udp?tags=1001|control-mode=common" // after "aeron:udp?tags=1001|control-mode=manual|control=..." and "aeron:udp?tags=1002|control-mode=common"
Defensive patterns
Strategy: validation
Validate before calling
Map<String,String> tagToMode = new HashMap<>();
String mode = extractParam(uri, "control-mode");
String prev = tagToMode.putIfAbsent(tag, mode);
if (prev != null && !prev.equals(mode)) throw new IllegalArgumentException("tag " + tag + " reused with different control-mode"); Type guard
static boolean controlModesMatch(String uriA, String uriB) { return Objects.equals(extractParam(uriA, "control-mode"), extractParam(uriB, "control-mode")); } Try / catch
try { return channel.isEquivalentTo(other); } catch (IllegalArgumentException e) { log.warn("tagged channel mismatch: {}", e.getMessage()); return false; } Prevention
- Generate all channel URIs sharing a tag from one template
- Assign unique tags per logical channel
- Include control-mode in tag-registry records
When it happens
Trigger: Creating two subscriptions/publications whose URIs both set tags=... (matching tag) but one uses control-mode=manual and the other control-mode=common (or omits it).
Common situations: MDC setups where a dynamic control channel and a manual one reuse the same tag, config drift between services sharing a tag.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- entityTag already in use: existingChannel= channel=
- matching tag= has mismatched endpoint or control: <>
- Aeron URIs must start with 'aeron:', found
- channelReceiveTimestampOffset must be a number or the value
- channelSendTimestampOffset must be a number or the value
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/07b804e3a48e31f5.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/media/UdpChannel.java:793
*
* @param udpChannel to match against.
* @param localAddress local address override to use for this channel.
* @param remoteAddress remote address override to use for this channel.
* @return true if there is a match otherwise false.
*/
public boolean matchesTag(
final UdpChannel udpChannel,
final InetSocketAddress localAddress,
final InetSocketAddress remoteAddress)
{
if (!hasTag || !udpChannel.hasTag() || tag != udpChannel.tag())
{
return false;
}
if (!hasMatchingControlMode(udpChannel))
{
throw new IllegalArgumentException(
"matching tag=" + tag + " has mismatched control-mode: " + uriStr + " <> " + udpChannel.uriStr);
}
if (!hasMatchingAddress(udpChannel, localAddress, remoteAddress))
{
throw new IllegalArgumentException(
"matching tag=" + tag + " has mismatched endpoint or control: " + uriStr + " <> " + udpChannel.uriStr);
}
return true;
}
private boolean isWildcard()
{
return remoteData.getAddress().isAnyLocalAddress() &&
remoteData.getPort() == 0 &&
localData.getAddress().isAnyLocalAddress() &&
localData.getPort() == 0;View on GitHub (pinned to 6d60124e15)