aeron-io/aeron · error · IllegalStateException

Initial window greater than SO_RCVBUF for channel: rcv-wnd=

Error message

Initial window greater than SO_RCVBUF for channel: rcv-wnd=<receiverWindowLength> so-rcvbuf=<channelSocketRcvbufLength> existingChannel=<existingChannel> channel=<channel>

What it means

Aeron validates that a subscription's initial receiver window (rcv-wnd) does not exceed the channel's SO_RCVBUF when an explicit so-rcvbuf is set. An initial window larger than the socket receive buffer can lose data, so the driver throws IllegalStateException, including the existing channel when merging with an existing subscription.

Solutions

  1. Raise so-rcvbuf in the channel URI to at least the receiver-window-length value.
  2. Lower receiver-window-length so it does not exceed so-rcvbuf.
  3. Increase the OS receive buffer limits (net.core.rmem_max on Linux) if so-rcvbuf cannot be applied.
  4. Align parameters with any existing subscription on the same channel to avoid merge-time conflicts.

Example fix

// before
"aeron:udp?endpoint=localhost:40456|rcv-wnd=8388608|so-rcvbuf=1048576"
// after
"aeron:udp?endpoint=localhost:40456|rcv-wnd=8388608|so-rcvbuf=8388608"
Defensive patterns

Strategy: validation

Validate before calling

if (soRcvbuf > 0 && rcvWnd > soRcvbuf) {
    throw new IllegalArgumentException("rcv-wnd (" + rcvWnd + ") must be <= so-rcvbuf (" + soRcvbuf + ")");
}

Try / catch

try {
    subscription = aeron.addSubscription(channel, streamId, availableImageHandler, null);
} catch (AeronException e) {
    if (e.getMessage().startsWith("Initial window greater than SO_RCVBUF")) { /* raise so-rcvbuf or lower rcv-wnd */ }
    throw e;
}

Prevention

When it happens

Trigger: Adding a subscription whose receiver-window-length param exceeds the URI's so-rcvbuf value (which must be > 0), e.g. ...|rcv-wnd=8388608|so-rcvbuf=1048576.

Common situations: Tuning for throughput by raising rcv-wnd while so-rcvbuf remains small; OS limits capping the actual SO_RCVBUF; merging subscriptions where an existing channel has a smaller buffer.

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


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/49f0364378e17cda. Report an issue: GitHub.

Appendix: source

Thrown at aeron-driver/src/main/java/io/aeron/driver/SubscriptionParams.java:177

            channelUri, UNTETHERED_RESTING_TIMEOUT_PARAM_NAME, ctx.untetheredRestingTimeoutNs());
    }

    private static long getTimeoutNs(final ChannelUri channelUri, final String paramName, final long defaultValue)
    {
        final String timeoutString = channelUri.get(paramName);
        return null != timeoutString ? SystemUtil.parseDuration(paramName, timeoutString) : defaultValue;
    }

    static void validateInitialWindowForRcvBuf(
        final SubscriptionParams params,
        final String channel,
        final int channelSocketRcvbufLength,
        final MediaDriver.Context ctx,
        final String existingChannel)
    {
        if (0 != channelSocketRcvbufLength && params.receiverWindowLength > channelSocketRcvbufLength)
        {
            throw new IllegalStateException(
                "Initial window greater than SO_RCVBUF for channel: rcv-wnd=" + params.receiverWindowLength +
                " so-rcvbuf=" + channelSocketRcvbufLength +
                (null == existingChannel ? "" : (" existingChannel=" + existingChannel)) + " channel=" + channel);
        }
        else if (0 == channelSocketRcvbufLength && params.receiverWindowLength > ctx.osDefaultSocketRcvbufLength())
        {
            throw new IllegalStateException(
                "Initial window greater than SO_RCVBUF for channel: rcv-wnd=" + params.receiverWindowLength +
                " so-rcvbuf=" + ctx.osDefaultSocketRcvbufLength() + " (OS default)" +
                (null == existingChannel ? "" : (" existingChannel=" + existingChannel)) + " channel=" + channel);
        }
    }

    public String toString()
    {
        return "SubscriptionParams" +
            "\n{" +
            "\n    initialTermId=" + initialTermId +

View on GitHub (pinned to 6d60124e15)