aeron-io/aeron · error · InvalidChannelException

destinations must not contain the key

Error message

destinations must not contain the key: {invalidKey} channel={destinationUri}

What it means

When validating destination URIs (for MDC manual destinations, multi-destination publications, or terminals), the driver rejects URIs containing keys that are meaningless or illegal in a destination context (INVALID_DESTINATION_KEYS, e.g. control-related params reserved for the owning channel). The offending key name is included in the message.

Solutions

  1. Strip the offending key from the destination URI before adding it.
  2. Build destinations from minimal URIs (endpoint or control only, e.g. "aeron:udp?endpoint=host:port").
  3. Validate destination URIs with ChannelUri.parse and reject disallowed keys before calling the API.

Example fix

// before
publication.addDestination("aeron:udp?endpoint=h:40456|control-mode=manual");
// after
publication.addDestination("aeron:udp?endpoint=h:40456");
Defensive patterns

Strategy: validation

Validate before calling

ChannelUri uri = ChannelUri.parse(destination);
for (String bad : new String[]{"control-mode", "session-id"})
  if (uri.containsKey(bad)) throw new IllegalArgumentException("destination must not contain key: " + bad);

Type guard

boolean isCleanDestination(ChannelUri uri) {
  return !uri.containsKey("control-mode"); // plus any other INVALID_DESTINATION_KEYS
}

Try / catch

try { publication.addDestination(destination); }
catch (InvalidChannelException e) { if (e.getMessage().startsWith("destinations must not contain the key")) { /* rebuild minimal URI */ } else throw e; }

Prevention

When it happens

Trigger: Calling Publication.addDestination()/removeDestination() or addRcvDestination() with a URI containing a forbidden key (e.g. control-mode, session-id, or other keys in INVALID_DESTINATION_KEYS).

Common situations: Reusing a full channel URI as a destination string including control params; template-generated URIs carrying extra parameters; copy-paste of subscription channel into destination list.

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/88c67a58bb2b35f5. Report an issue: GitHub.

Appendix: source

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

            throw new InvalidChannelException(
                "Media timestamps '" + MEDIA_RCV_TIMESTAMP_OFFSET_PARAM_NAME +
                    "' are not supported in the Java driver: channel=" + udpChannel.originalUriString());
        }
    }

    private static void validateDestinationUri(final ChannelUri uri, final String destinationUri)
    {
        if (SPY_QUALIFIER.equals(uri.prefix()))
        {
            throw new InvalidChannelException("Aeron spies are invalid as send destinations: channel=" +
                destinationUri);
        }

        for (final String invalidKey : INVALID_DESTINATION_KEYS)
        {
            if (uri.containsKey(invalidKey))
            {
                throw new InvalidChannelException(
                    "destinations must not contain the key: " + invalidKey + " channel=" + destinationUri);
            }
        }

        if (Objects.equals(CONTROL_MODE_RESPONSE, uri.get(MDC_CONTROL_MODE_PARAM_NAME)))
        {
            throw new InvalidChannelException("destinations may not specify " +
                MDC_CONTROL_MODE_PARAM_NAME + "=" + CONTROL_MODE_RESPONSE);
        }
    }

    private static void validateSendDestinationUri(final ChannelUri uri, final String destinationUri)
    {
        final String endpoint = uri.get(ENDPOINT_PARAM_NAME);

        if (null != endpoint && endpoint.endsWith(":0"))
        {
            throw new InvalidChannelException(ENDPOINT_PARAM_NAME + " has port=0 for send destination: channel=" +

View on GitHub (pinned to 6d60124e15)