{"record":{"id":"9bdfca6c3c366583","repo":"apache/hadoop","slug":"path-must-be-absolute-path","errorCode":null,"errorMessage":"Path must be absolute: \" + path","messagePattern":"Path must be absolute: \" \\+ path","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-bos/src/main/java/org/apache/hadoop/fs/bos/BaiduBosFileSystem.java","lineNumber":89,"sourceCode":"  private BosNativeFileSystemStore store;\n  private Path workingDir;\n  private long readAhead;\n  private int readBufferSize;\n  private boolean forceGetNonHierarchyMetadataInListStatus;\n\n  /** Default constructor. */\n  public BaiduBosFileSystem() {\n  }\n\n  /**\n   * Convert a path to a BOS object key.\n   *\n   * @param path the path to convert\n   * @return the BOS object key\n   */\n  protected String pathToKey(Path path) {\n    if (!path.isAbsolute()) {\n      throw new IllegalArgumentException(\n          \"Path must be absolute: \" + path);\n    }\n    checkPath(path);\n    return path.toUri().getPath().substring(1);\n  }\n\n  private static Path keyToPath(String key) {\n    return new Path(\"/\" + key);\n  }\n\n  @Override\n  public String getScheme() {\n    return \"bos\";\n  }\n\n  @Override\n  public void close() throws IOException {\n    try {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-bos/src/main/java/org/apache/hadoop/fs/bos/BaiduBosFileSystem.java#L71-L107","documentation":"StreamKeyValUtil.splitKeyVal splits a raw UTF-8 byte array into Hadoop Text key and value at a caller-supplied splitPos, and it validates that splitPos falls inside the half-open range [start, start+length). An IllegalArgumentException with 'splitPos must be in the range' means the computed separator offset lies outside the record buffer, so the split is not merely wrong but impossible. The library throws it to prevent key.set/val.set from reading out of bounds.","triggerScenarios":"Calling any splitKeyVal overload (StreamKeyValUtil.java:65-121) with a splitPos < start, >= start+length, or negative — typically a separator index found by String.indexOf on a different buffer, a separator not found (-1), or a key length >= record length (e.g. separatorLength=1 leaves a zero/negative value half).","commonSituations":"Custom streaming mappers/reducers using TypedBytesOutput or raw key/value copying (e.g. copyPartition/hadoopStreaming custom IO classes); setting -stream.map.output.field.separator or stream.io.key.length and getting the field index math wrong; records with no separator so the boundary computes past the end of the line; empty input lines.","solutions":["Recompute the separator position on the same utf buffer with start offset added: splitPos = start + line.indexOf(sep, start), and use -1 handling before calling splitKeyVal.","If you derive key length instead, clamp it: splitPos = Math.min(Math.max(splitPos, start), start + length - 1).","For 'no separator present' records either skip them or fall back to whole-record-as-key (splitPos = start + length - 1 with separatorLength 0 semantics) instead of passing indexOf result directly.","Unit-test with edge cases: empty line, line equal to separator, separator at last byte."],"exampleFix":"// before\nint pos = new String(utf, start, length).indexOf('\\t');\nStreamKeyValUtil.splitKeyVal(utf, start, length, key, val, pos, 1); // pos relative -> throws when start>0\n\n// after\nint pos = new String(utf, start, length).indexOf('\\t');\nif (pos < 0) {\n  pos = length - 1; // whole record as key, empty value\n} else {\n  pos = start + pos; // make buffer-absolute\n}\nStreamKeyValUtil.splitKeyVal(utf, start, length, key, val, pos, 1);","handlingStrategy":"validation","validationCode":"static int resolveSplitPos(byte[] utf, int start, int length, int sepIdxInRecord, int separatorLength) {\n  if (sepIdxInRecord < 0) return start + length - 1; // no separator: whole record as key\n  int splitPos = start + sepIdxInRecord;              // make buffer-absolute\n  if (splitPos < start || splitPos >= start + length)\n    throw new IllegalArgumentException(\"bad splitPos \" + splitPos);\n  return splitPos;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compute separator index on the same buffer/offset you pass to splitKeyVal (always add start).","Handle indexOf == -1 before calling splitKeyVal.","Never let keyLen exceed length - separatorLength."],"tags":["hadoop","streaming","validation","illegal-argument","key-value"],"backgroundTag":"argument-out-of-range","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}