aeron-io/aeron · error · IllegalStateException

MTU greater than SO_SNDBUF for channel: mtu=

Error message

MTU greater than SO_SNDBUF for channel: mtu=<mtuLength> so-sndbuf=<osDefaultSocketSndbufLength> (OS default) existingChannel=<existingChannel> channel=<channel>

What it means

Same rule as the explicit so-sndbuf case: when the channel does not specify so-sndbuf, Aeron compares the MTU against the OS default socket send buffer (osDefaultSocketSndbufLength) and throws IllegalStateException if MTU exceeds it. The '(OS default)' marker in the message indicates this branch.

Solutions

  1. Lower the mtu URI value to fit the OS default send buffer
  2. Increase the OS default: sysctl -w net.core.wmem_default=<value> (and persist in /etc/sysctl.conf)
  3. Add an explicit so-sndbuf to the channel URI at least equal to the MTU
  4. Verify with `cat /proc/sys/net/core/wmem_default` before choosing MTU

Example fix

// before
"aeron:udp?endpoint=localhost:40456|mtu=8948"  // OS default SNDBUF is 4096
// after (either)
"aeron:udp?endpoint=localhost:40456|mtu=8948|so-sndbuf=16384"
// or shell: sysctl -w net.core.wmem_default=16384
Defensive patterns

Strategy: validation

Validate before calling

long osDefault = Long.parseLong(
    java.nio.file.Files.readString(java.nio.file.Path.of("/proc/sys/net/core/wmem_default")).trim());
if (mtu > osDefault && uriLacksParam("so-sndbuf")) throw new IllegalArgumentException("mtu exceeds OS default SNDBUF");

Try / catch

try { publication = aeron.addPublication(uri, streamId); }
catch (IllegalStateException e) {
    if (e.getMessage().contains("(OS default)")) {
        throw new ConfigurationException("Increase net.core.wmem_default or set so-sndbuf in the channel URI", e);
    } throw e;
}

Prevention

When it happens

Trigger: Adding a network publication with a large `mtu=` URI value while the channel has no `so-sndbuf` param and the OS default SNDBUF (net.core.wmem_default) is smaller than the MTU.

Common situations: Linux hosts with default wmem_default (~212992) are usually fine, but constrained containers/VMs or explicitly shrunk sysctl defaults break large-MTU configs; cloud instances with low defaults.

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/6052119073012fb2. Report an issue: GitHub.

Appendix: source

Thrown at aeron-driver/src/main/java/io/aeron/driver/PublicationParams.java:391

    static void validateMtuForSndbuf(
        final PublicationParams params,
        final int channelSocketSndbufLength,
        final MediaDriver.Context ctx,
        final String channel,
        final String existingChannel)
    {
        if (0 != channelSocketSndbufLength && params.mtuLength > channelSocketSndbufLength)
        {
            throw new IllegalStateException(
                "MTU greater than SO_SNDBUF for channel: mtu=" + params.mtuLength +
                " so-sndbuf=" + channelSocketSndbufLength +
                (null == existingChannel ? "" : (" existingChannel=" + existingChannel)) +
                " channel=" + channel);
        }
        else if (0 == channelSocketSndbufLength && params.mtuLength > ctx.osDefaultSocketSndbufLength())
        {
            throw new IllegalStateException(
                "MTU greater than SO_SNDBUF for channel: mtu=" + params.mtuLength +
                " so-sndbuf=" + ctx.osDefaultSocketSndbufLength() + " (OS default)" +
                (null == existingChannel ? "" : (" existingChannel=" + existingChannel)) +
                " channel=" + channel);
        }
    }

    private void getLingerTimeoutNs(final ChannelUri channelUri, final MediaDriver.Context ctx)
    {
        final String lingerParam = channelUri.get(LINGER_PARAM_NAME);
        if (null != lingerParam)
        {
            lingerTimeoutNs = SystemUtil.parseDuration(LINGER_PARAM_NAME, lingerParam);
        }
        else
        {
            lingerTimeoutNs = ctx.publicationLingerTimeoutNs();
        }

View on GitHub (pinned to 6d60124e15)