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
- Raise so-rcvbuf in the channel URI to at least the receiver-window-length value.
- Lower receiver-window-length so it does not exceed so-rcvbuf.
- Increase the OS receive buffer limits (net.core.rmem_max on Linux) if so-rcvbuf cannot be applied.
- 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
- Keep so-rcvbuf >= rcv-wnd in channel configs.
- Check OS net.core.rmem_max when tuning large windows.
- Use consistent params across subscriptions sharing a channel.
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
- Initial window greater than SO_RCVBUF for channel: rcv-wnd=
- could not re-resolve: control=
- could not re-resolve: endpoint=
- could not resolve control address:
- could not resolve endpoint address:
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)