apache/beam · error · IllegalArgumentException

offset is negative:

Error message

offset is negative: 

What it means

TextSource.SubstringByteArrayOutputStream.toString(int offset, int length, Charset) validates its arguments before creating a substring from the internal buffer. If offset is negative it throws IllegalArgumentException immediately. This guard exists because a negative offset would otherwise be an ArrayIndexOutOfBoundsException or produce silent wrong output in the underlying ByteArrayOutputStream.toString.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/io/TextSource.java:472

      str.reset();
      return true;
    }
  }

  /**
   * This class is created to avoid multiple bytes-copy when making a substring of the output.
   * Without this class, it requires two bytes copies.
   *
   * <pre>{@code
   * ByteArrayOutputStream out = ...;
   * byte[] buffer = out.toByteArray(); // 1st-copy
   * String s = new String(buffer, offset, length); // 2nd-copy
   * }</pre>
   */
  static class SubstringByteArrayOutputStream extends ByteArrayOutputStream {
    public String toString(int offset, int length, Charset charset) {
      if (offset < 0) {
        throw new IllegalArgumentException("offset is negative: " + offset);
      }
      if (offset > count) {
        throw new IllegalArgumentException(
            "offset exceeds the buffer limit. offset: " + offset + ", limit: " + count);
      }

      if (length < 0) {
        throw new IllegalArgumentException("length is negative: " + length);
      }

      if (offset + length > count) {
        throw new IllegalArgumentException(
            "offset + length exceeds the buffer limit. offset: "
                + offset
                + ", length: "
                + length
                + ", limit: "
                + count);

View on GitHub (pinned to 12126d8942)

Solutions

  1. Validate/normalize the offset before calling: Math.max(0, offset) or check `if (offset >= 0)` in caller code.
  2. Fix the computation producing the negative offset (e.g. re-derive start position from the record delimiter index).
  3. If offset is intentionally invalid, throw a descriptive error in caller code instead of reaching the buffer slicing API.

Example fix

// before
String s = substringBuffer.toString(start - headerSize, recordLength, StandardCharsets.UTF_8);

// after
int off = Math.max(0, start - headerSize);
String s = substringBuffer.toString(off, recordLength, StandardCharsets.UTF_8);
Defensive patterns

Strategy: validation

Validate before calling

checkArgument(offset >= 0, "offset must be non-negative, got %s", offset);

Try / catch

try {
  String s = buffer.toString(offset, len, UTF_8);
} catch (IllegalArgumentException e) {
  throw new IllegalStateException("bad record slice: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling toString(offset, length, charset) on a SubstringByteArrayOutputStream with offset < 0, typically when a caller computed the offset from a subtraction (e.g. start - something) that underflowed or used an uninitialized value.

Common situations: Custom record boundary logic in TextSource subclasses computing substring offsets from header sizes; tests exercising invalid ranges; off-by-one bugs where an index variable was decremented below zero before slicing the buffer.

Related errors


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