{"record":{"id":"ac38137a7309d302","repo":"apache/hadoop","slug":"negative-position-ac3813","errorCode":null,"errorMessage":"Negative Position","messagePattern":"Negative Position","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/web/ByteRangeInputStream.java","lineNumber":133,"sourceCode":"      if (in != null) {\n        in.close();\n      }\n      InputStreamAndFileLength fin = openInputStream(startPos);\n      in = fin.in;\n      fileLength = fin.length;\n      status = StreamStatus.NORMAL;\n      break;\n    case CLOSED:\n      throw new IOException(\"Stream closed\");\n    }\n    return in;\n  }\n\n  @VisibleForTesting\n  protected InputStreamAndFileLength openInputStream(long startOffset)\n      throws IOException {\n    if (startOffset < 0) {\n      throw new EOFException(\"Negative Position\");\n    }\n    // Use the original url if no resolved url exists, eg. if\n    // it's the first time a request is made.\n    final boolean resolved = resolvedURL.getURL() != null;\n    final URLOpener opener = resolved? resolvedURL: originalURL;\n\n    final HttpURLConnection connection = opener.connect(startOffset, resolved);\n    resolvedURL.setURL(getResolvedUrl(connection));\n\n    InputStream in = connection.getInputStream();\n    final Long length;\n    final Map<String, List<String>> headers = connection.getHeaderFields();\n    if (isChunkedTransferEncoding(headers)) {\n      // file length is not known\n      length = null;\n    } else {\n      // for non-chunked transfer-encoding, get content-length\n      final String cl = connection.getHeaderField(HttpHeaders.CONTENT_LENGTH);","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/web/ByteRangeInputStream.java#L115-L151","documentation":"ByteRangeInputStream.seek() deliberately does not validate the position; it just records startPos/currentPos and marks the stream SEEK. The check happens lazily on the next read, when openInputStream(startPos) throws EOFException for any negative offset. So this error means seek(negative) (or an equivalent state) was followed by a read on a WebHDFS input stream.","triggerScenarios":"Call seek(p) with p < 0 on a WebHDFS FSDataInputStream, then read — e.g., computing an offset with getPos() - n where n exceeds the current position, or seeding a seek from an uninitialized -1 variable.","commonSituations":"Offset arithmetic that underflows near the start of the file (reading the last N bytes of a prefix), passing -1 sentinels from parsers/regex match results into seek, or position values derived from user input without validation.","solutions":["Validate the offset before seeking: if (pos < 0) throw/fallback — positions are non-negative by contract","Fix the arithmetic: when reading backwards, clamp to 0 with Math.max(0, getPos() - n)","Treat -1 from any matcher/index API as 'not found' and never feed it to seek()"],"exampleFix":"// before\nlong pos = Math.max(0, in.getPos() - tailLen);\nin.seek(pos);\n\n// after\nlong pos = in.getPos() - tailLen;\nif (pos < 0) {\n  throw new IllegalArgumentException(\"seek offset \" + pos + \" is negative\");\n}\nin.seek(pos);","handlingStrategy":"validation","validationCode":"if (targetPos < 0) {\n  throw new IllegalArgumentException(\"seek position must be >= 0, got \" + targetPos);\n}\nin.seek(targetPos);","typeGuard":null,"tryCatchPattern":"try {\n  in.seek(pos); in.read(buf);\n} catch (EOFException e) {\n  if (\"Negative Position\".equals(e.getMessage())) {\n    throw new IllegalArgumentException(\"computed a negative seek offset: \" + pos, e);\n  }\n  throw e;\n}","preventionTips":["Clamp backward offsets: Math.max(0, getPos() - n)","Never pass matcher/index results (-1 = not found) into seek()","Note seek() itself never throws this — it always surfaces on the NEXT read, so validate eagerly"],"tags":["hdfs","webhdfs","io","seek","offset-validation"],"backgroundTag":"negative-seek-offset","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}