grpc/grpc-java · error · IndexOutOfBoundsException

EOF trying to read ${length} bytes

Error message

EOF trying to read ${length} bytes

What it means

OkHttpReadableBuffer.readBytes throws IndexOutOfBoundsException 'EOF trying to read N bytes' when the underlying okio Buffer is exhausted before `length` bytes can be read. It indicates the received frame was truncated or the buffer accounting between HTTP/2 framing and the gRPC message buffer is wrong.

Source

Thrown at okhttp/src/main/java/io/grpc/okhttp/OkHttpReadableBuffer.java:66

  }

  private void fakeEofExceptionMethod() throws EOFException {}

  @Override
  public void skipBytes(int length) {
    try {
      buffer.skip(length);
    } catch (EOFException e) {
      throw new IndexOutOfBoundsException(e.getMessage());
    }
  }

  @Override
  public void readBytes(byte[] dest, int destOffset, int length) {
    while (length > 0) {
      int bytesRead = buffer.read(dest, destOffset, length);
      if (bytesRead == -1) {
        throw new IndexOutOfBoundsException("EOF trying to read " + length + " bytes");
      }
      length -= bytesRead;
      destOffset += bytesRead;
    }
  }

  @Override
  public void readBytes(OutputStream dest, int length) throws IOException {
    buffer.writeTo(dest, length);
  }

  @Override
  public ReadableBuffer readBytes(int length) {
    okio.Buffer buf = new okio.Buffer();
    buf.write(buffer, length);
    return new OkHttpReadableBuffer(buf);
  }

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Retry the RPC; a truncated frame usually means the stream failed mid-transfer
  2. Check network path for proxies/load balancers that truncate large responses (raise proxy limits, disable buffering)
  3. Upgrade grpc-okhttp / grpc-netty to rule out known framing bugs
  4. Enable gRPC/okhttp logging and HTTP/2 frame traces to find where the truncation occurs

Example fix

// before
// receiving side trusts message length; peer sends shorter frame -> EOF
// after
// enforce max inbound message size so oversized/corrupt lengths fail fast:
OkHttpChannelBuilder.forAddress(host, port).maxInboundMessageSize(4 * 1024 * 1024).build();
Defensive patterns

Strategy: retry

Validate before calling

// enforce sane inbound size before sending large messages
if (msg.size() > maxInboundMessageSize) throw new IllegalArgumentException("message too large");

Try / catch

try { stub.unaryCall(req); } catch (StatusRuntimeException e) { if (e.getStatus().getCode() == Status.Code.INTERNAL || e.getStatus().getCode() == Status.Code.UNAVAILABLE) { retryWithBackoff(); } throw e; }

Prevention

When it happens

Trigger: Reading a serialized gRPC message from a transport buffer where fewer bytes arrived than the message header declared (truncated frame, stream reset mid-message, or corrupt length prefix).

Common situations: Network interruption cutting a DATA frame short, HTTP/2 flow-control or framing bugs, proxies that truncate long responses, mismatched message length fields from a faulty peer.

Related errors


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