{"record":{"id":"8853cb4ed10d41de","repo":"apache/hadoop","slug":"http-stream-closed-before-all-bytes-were-read-exp","errorCode":null,"errorMessage":"HTTP stream closed before all bytes were read. Expected %,d bytes but only read %,d bytes. Current position %,d (%s)","messagePattern":"HTTP stream closed before all bytes were read\\. Expected %,d bytes but only read %,d bytes\\. Current position %,d \\((.+?)\\)","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AInputStream.java","lineNumber":1131,"sourceCode":"   * @throws EOFException if EOF if read() call returns -1\n   * @throws InterruptedIOException if vectored IO operation is stopped.\n   */\n  private void readByteArray(InputStream objectContent,\n                            final FileRange range,\n                            byte[] dest,\n                            int offset,\n                            int length) throws IOException {\n    LOG.debug(\"Reading {} bytes\", length);\n    int readBytes = 0;\n    long position = range.getOffset();\n    while (readBytes < length) {\n      checkIfVectoredIOStopped();\n      int readBytesCurr = objectContent.read(dest,\n              offset + readBytes,\n              length - readBytes);\n      LOG.debug(\"read {} bytes from stream\", readBytesCurr);\n      if (readBytesCurr < 0) {\n        throw new EOFException(\n            String.format(\"HTTP stream closed before all bytes were read.\"\n                    + \" Expected %,d bytes but only read %,d bytes. Current position %,d\"\n                    + \" (%s)\",\n                length, readBytes, position, range));\n      }\n      readBytes += readBytesCurr;\n      position += readBytesCurr;\n\n      // update io stats incrementally\n      incrementBytesRead(readBytesCurr);\n    }\n  }\n\n  /**\n   * Read data from S3 with retries for the GET request\n   * This also handles if file has been changed while the\n   * http call is getting executed. If the file has been\n   * changed RemoteFileChangedException is thrown.","sourceCodeStart":1113,"sourceCodeEnd":1149,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AInputStream.java#L1113-L1149","documentation":"Thrown while filling one requested range during readVectored(): objectContent.read() returned -1 before the range's length bytes arrived. The range was issued as a Content-Range GET, so a short body means the connection was cut or the object changed mid-transfer; S3A aborts that range with this EOFException.","triggerScenarios":"readVectored() where a range's body terminates early: connection reset between the cluster and S3, S3 closing the socket mid-body, or the object being truncated/replaced while the range streams.","commonSituations":"Network instability or NAT/proxy timeouts during large columnar reads; objects actively rewritten by another writer during a long query; intermittent S3 connection drops on long-running scans.","solutions":["Retry the read by reopening the stream - a new GET re-issues the exact range","If persistent, check fs.s3a.connection.timeout, socket buffer settings, and any proxy idle-timeout on the S3 endpoint","Verify the object's current length/ETag when concurrent overwrite is possible and fail fast with a clearer error","As a workaround, use plain positioned reads (readFully) instead of vectored reads for the affected job"],"exampleFix":"// before\nList<CompletableFuture<ByteBuffer>> futs = in.readVectored(ranges, ByteBuffer::allocate);\nByteBuffer b = futs.get(0).join(); // EOFException: HTTP stream closed before all bytes were read\n\n// after - retry the whole vectored read on a fresh stream\nfor (int i = 1; i <= 3; i++) {\n  try (FSDataInputStream fresh = fs.open(path)) {\n    List<CompletableFuture<ByteBuffer>> f = fresh.readVectored(ranges, ByteBuffer::allocate);\n    return f.get(0).join();\n  } catch (CompletionException e) {\n    if (!(e.getCause() instanceof EOFException) || i == 3) throw e;\n  }\n}","handlingStrategy":"retry","validationCode":"long len = fs.getFileStatus(path).getLen();\nfor (ByteRange r : ranges) {\n  if (r.getOffset() < 0 || r.getOffset() + r.getLength() > len) {\n    throw new IllegalArgumentException(\"Range outside object: \" + r);\n  }\n}","typeGuard":null,"tryCatchPattern":"catch EOFException (or CompletionException/ExecutionException wrapping it from the futures), reopen the stream, and retry the same ranges a bounded number of times with backoff; verify the object length between attempts if concurrent rewrites are possible","preventionTips":["Set fs.s3a.connection.timeout appropriate to the size of vectored ranges","Fix proxy/NAT idle timeouts that cut long S3 GETs","Watch S3A instrumentation for vectored-read failures to detect flaky links early"],"tags":["s3a","hadoop-aws","vectored-read","eofexception","truncated-response","network"],"backgroundTag":"truncated-http-response","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}