grpc/grpc-java · error · IllegalArgumentException

Invalid initial window size: ${newWindowSize}

Error message

Invalid initial window size: ${newWindowSize}

What it means

OutboundFlowController.initialOutboundWindowSize sets the HTTP/2 connection-level outbound window and validates the new size. A negative value is a programming error, so it throws IllegalArgumentException 'Invalid initial window size: <n>'.

Source

Thrown at okhttp/src/main/java/io/grpc/okhttp/OutboundFlowController.java:61

  public OutboundFlowController(Transport transport, FrameWriter frameWriter) {
    this.transport = Preconditions.checkNotNull(transport, "transport");
    this.frameWriter = Preconditions.checkNotNull(frameWriter, "frameWriter");
    this.initialWindowSize = DEFAULT_WINDOW_SIZE;
    connectionState = new StreamState(CONNECTION_STREAM_ID, DEFAULT_WINDOW_SIZE, null);
  }

  /**
   * Adjusts outbound window size requested by peer. When window size is increased, it does not send
   * any pending frames. If this method returns {@code true}, the caller should call {@link
   * #writeStreams()} after settings ack.
   *
   * <p>Must be called with holding transport lock.
   *
   * @return true, if new window size is increased, false otherwise.
   */
  public boolean initialOutboundWindowSize(int newWindowSize) {
    if (newWindowSize < 0) {
      throw new IllegalArgumentException("Invalid initial window size: " + newWindowSize);
    }

    int delta = newWindowSize - initialWindowSize;
    initialWindowSize = newWindowSize;
    for (StreamState state : transport.getActiveStreams()) {
      state.incrementStreamWindow(delta);
    }

    return delta > 0;
  }

  /**
   * Update the outbound window for given stream, or for the connection if stream is null. Returns
   * the new value of the window size.
   *
   * <p>Must be called with holding transport lock.
   */
  public int windowUpdate(@Nullable StreamState state, int delta) {

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Validate the window size is >= 0 before calling (and realistically within HTTP/2 max 2^31-1)
  2. Check the code computing the new size for sign/parse errors
  3. Clamp peer-advertised SETTINGS_INITIAL_WINDOW_SIZE values to valid range before applying

Example fix

// before
controller.initialOutboundWindowSize(size);
// after
if (size >= 0 && size <= Integer.MAX_VALUE) { controller.initialOutboundWindowSize(size); }
Defensive patterns

Strategy: validation

Validate before calling

if (newWindowSize < 0 || newWindowSize > Integer.MAX_VALUE) throw new IllegalArgumentException("window size out of range: " + newWindowSize);

Try / catch

try { controller.initialOutboundWindowSize(size); }
catch (IllegalArgumentException e) { /* clamp size and retry */ controller.initialOutboundWindowSize(Math.max(0, size)); }

Prevention

When it happens

Trigger: Calling initialOutboundWindowSize with a negative int, or code (e.g. from SETTINGS_WINDOW_UPDATE handling) passing a parsed value that underflowed/negative into this method.

Common situations: Custom transport wiring or tests feeding unvalidated HTTP/2 SETTINGS values; integer parsing mistakes when handling peer SETTINGS frames.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/92b86d82383ec16a. Report an issue: GitHub.