apache/beam · error · IllegalArgumentException

Initial capacity < 0

Error message

Initial capacity < 0

What it means

ByteStringOutputStream's constructor validates its initialCapacity argument and throws IllegalArgumentException if it is negative. The capacity sizes the internal byte buffer, which cannot have negative length.

Solutions

  1. Validate the computed capacity is non-negative before constructing, clamping to 0 or a sane minimum
  2. Use the no-arg ByteStringOutputStream() constructor when no meaningful capacity is known
  3. Fix the size-estimation arithmetic that produced the negative number

Example fix

// before
int capacity = estimatedSize - headerSize; // can be negative
ByteStringOutputStream out = new ByteStringOutputStream(capacity);
// after
int capacity = Math.max(0, estimatedSize - headerSize);
ByteStringOutputStream out = new ByteStringOutputStream(capacity);
Defensive patterns

Strategy: validation

Validate before calling

if (capacity < 0) {
  throw new IllegalArgumentException("computed capacity is negative: " + capacity);
}
ByteStringOutputStream out = new ByteStringOutputStream(capacity);

Try / catch

try {
  ByteStringOutputStream out = new ByteStringOutputStream(capacity);
} catch (IllegalArgumentException e) {
  ByteStringOutputStream out = new ByteStringOutputStream(); // fall back to default
}

Prevention

When it happens

Trigger: Calling new ByteStringOutputStream(n) with n < 0, typically when capacity is computed from a formula (e.g. estimated size, subtraction like available - consumed) that yields a negative value.

Common situations: Pre-sizing the stream based on an estimated encoded size that was computed as a difference of two sizes; misreading the API as accepting a default/unspecified value (there is an overloaded no-arg constructor for that).

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/e0e466fd1524d511. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/ByteStringOutputStream.java:73

  // Current buffer to which we are writing
  private byte[] buffer;

  // Location in buffer[] to which we write the next byte.
  private int bufferPos;

  /** Creates a new output stream with a default capacity. */
  public ByteStringOutputStream() {
    this(DEFAULT_CAPACITY);
  }

  /**
   * Creates a new output stream with the specified initial capacity.
   *
   * @param initialCapacity the initial capacity of the output stream.
   */
  public ByteStringOutputStream(int initialCapacity) {
    if (initialCapacity < 0) {
      throw new IllegalArgumentException("Initial capacity < 0");
    }
    this.buffer = new byte[initialCapacity];
    this.result = ByteString.EMPTY;
  }

  @Override
  public void write(int b) {
    if (bufferPos == buffer.length) {
      // We want to increase our total capacity by 50% but not larger than the max chunk size.
      result = result.concat(UnsafeByteOperations.unsafeWrap(buffer));
      buffer = new byte[Math.min(Math.max(1, result.size()), MAX_CHUNK_SIZE)];
      bufferPos = 0;
    }
    buffer[bufferPos++] = (byte) b;
  }

  @Override
  public void write(byte[] b, int offset, int length) {

View on GitHub (pinned to 12126d8942)