{"record":{"id":"57346a86940b39b0","repo":"apache/beam","slug":"length-is-negative","errorCode":null,"errorMessage":"length is negative: ","messagePattern":"length 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":480,"sourceCode":"   *\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);\n      }\n\n      return new String(buf, offset, length, charset);\n    }\n  }\n\n  /**\n   * See <a","sourceCodeStart":462,"sourceCodeEnd":498,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/io/TextSource.java#L462-L498","documentation":"SubstringByteArrayOutputStream.toString validates that the requested length is non-negative before copying bytes out of the buffer. A negative length indicates the caller computed the record size incorrectly (e.g. end position before start position) and the library fails fast with a clear message instead of a cryptic exception from lower-level array copies.","triggerScenarios":"Calling toString(offset, length, charset) with length < 0 — usually when length = end - start and end < start because record delimiters were searched in the wrong order or the delimiter was not found and -1 was used.","commonSituations":"Custom TextSource subclasses computing record lengths from indexOf results that returned -1; arithmetic on unsigned values stored in signed ints that overflowed; tests exercising invalid ranges.","solutions":["Check delimiter search results for -1 before computing length; handle not-found explicitly.","Validate length >= 0 in the caller (e.g. Preconditions.checkArgument(length >= 0)).","Fix the ordering of start/end computation so end >= start always holds for a found record."],"exampleFix":"// before\nint len = endIdx - startIdx; // endIdx can be -1\nString s = buffer.toString(startIdx, len, UTF_8);\n\n// after\ncheckState(endIdx >= 0, \"record delimiter not found\");\nint len = endIdx - startIdx;\nString s = buffer.toString(startIdx, len, UTF_8);","handlingStrategy":"validation","validationCode":"checkState(endIdx >= 0, \"record delimiter not found\");\ncheckArgument(endIdx - startIdx >= 0, \"record length must be non-negative\");","typeGuard":null,"tryCatchPattern":"try {\n  String s = buffer.toString(startIdx, len, UTF_8);\n} catch (IllegalArgumentException e) {\n  throw new IllegalStateException(\"invalid record length: \" + e.getMessage(), e);\n}","preventionTips":["Always check indexOf-style results for -1 before computing lengths.","Compute length as end - start only when end >= start is guaranteed.","Beware of int overflow when lengths derive from unsigned data."],"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"}