{"record":{"id":"15fdce3324e46466","repo":"apache/beam","slug":"offset-is-negative","errorCode":null,"errorMessage":"offset is negative: ","messagePattern":"offset is negative: ","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/io/TextSource.java","lineNumber":472,"sourceCode":"      str.reset();\n      return true;\n    }\n  }\n\n  /**\n   * This class is created to avoid multiple bytes-copy when making a substring of the output.\n   * Without this class, it requires two bytes copies.\n   *\n   * <pre>{@code\n   * ByteArrayOutputStream out = ...;\n   * byte[] buffer = out.toByteArray(); // 1st-copy\n   * String s = new String(buffer, offset, length); // 2nd-copy\n   * }</pre>\n   */\n  static class SubstringByteArrayOutputStream extends ByteArrayOutputStream {\n    public String toString(int offset, int length, Charset charset) {\n      if (offset < 0) {\n        throw new IllegalArgumentException(\"offset is negative: \" + offset);\n      }\n      if (offset > count) {\n        throw new IllegalArgumentException(\n            \"offset exceeds the buffer limit. offset: \" + offset + \", limit: \" + count);\n      }\n\n      if (length < 0) {\n        throw new IllegalArgumentException(\"length is negative: \" + length);\n      }\n\n      if (offset + length > count) {\n        throw new IllegalArgumentException(\n            \"offset + length exceeds the buffer limit. offset: \"\n                + offset\n                + \", length: \"\n                + length\n                + \", limit: \"\n                + count);","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/io/TextSource.java#L454-L490","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Validate/normalize the offset before calling: Math.max(0, offset) or check `if (offset >= 0)` in caller code.","Fix the computation producing the negative offset (e.g. re-derive start position from the record delimiter index).","If offset is intentionally invalid, throw a descriptive error in caller code instead of reaching the buffer slicing API."],"exampleFix":"// before\nString s = substringBuffer.toString(start - headerSize, recordLength, StandardCharsets.UTF_8);\n\n// after\nint off = Math.max(0, start - headerSize);\nString s = substringBuffer.toString(off, recordLength, StandardCharsets.UTF_8);","handlingStrategy":"validation","validationCode":"checkArgument(offset >= 0, \"offset must be non-negative, got %s\", offset);","typeGuard":null,"tryCatchPattern":"try {\n  String s = buffer.toString(offset, len, UTF_8);\n} catch (IllegalArgumentException e) {\n  throw new IllegalStateException(\"bad record slice: \" + e.getMessage(), e);\n}","preventionTips":["Validate offsets derived from arithmetic (especially subtraction) before slicing.","Clamp with Math.max(0, offset) when underflow is possible.","Add unit tests for zero and boundary offsets."],"tags":["java","apache-beam","io","argument-validation"],"backgroundTag":"argument-out-of-range","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}