{"record":{"id":"f0318646296f584e","repo":"apache/hadoop","slug":"stream-is-closed-f03186","errorCode":null,"errorMessage":"Stream is closed!","messagePattern":"Stream is closed!","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/BufferedFSInputStream.java","lineNumber":66,"sourceCode":"   * Creates a <code>BufferedFSInputStream</code>\n   * with the specified buffer size,\n   * and saves its  argument, the input stream\n   * <code>in</code>, for later use.  An internal\n   * buffer array of length  <code>size</code>\n   * is created and stored in <code>buf</code>.\n   *\n   * @param   in     the underlying input stream.\n   * @param   size   the buffer size.\n   * @exception IllegalArgumentException if size {@literal <=} 0.\n   */\n  public BufferedFSInputStream(FSInputStream in, int size) {\n    super(in, size);\n  }\n\n  @Override\n  public long getPos() throws IOException {\n    if (in == null) {\n      throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);\n    }\n    return ((FSInputStream)in).getPos()-(count-pos);\n  }\n\n  @Override\n  public long skip(long n) throws IOException {\n    if (n <= 0) {\n      return 0;\n    }\n\n    seek(getPos()+n);\n    return n;\n  }\n\n  @Override\n  public void seek(long pos) throws IOException {\n    if (in == null) {\n      throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/BufferedFSInputStream.java#L48-L84","documentation":"BufferedFSInputStream is the buffering wrapper used inside FSDataInputStream; once the stream is closed the underlying `in` reference is null, and getPos() checks that and throws IOException(\"Stream is closed!\") from FSExceptionMessages. This is a use-after-close lifecycle bug in the caller, not a filesystem I/O failure. Note that skip() calls getPos() first, so skip() on a closed stream surfaces this same error.","triggerScenarios":"FSDataInputStream.getPos() invoked after close(): progress reporting or final-offset logging in a finally block, a RecordReader computing input split progress after the input stream was closed, or a background thread (prefetch, metrics sampler) racing the close on another thread.","commonSituations":"MapReduce/Spark input-format cleanup orders close() before a last getPos() for counters; a stream held in a cache gets evicted/closed while a reader still holds it; exception handlers close the stream and generic retry logic then calls getPos on it.","solutions":["Fix the lifecycle: capture getPos() before close(), or restructure so nothing touches the stream after close (try-with-resources).","Ensure single ownership - only the component that opened the stream closes it, and no background threads outlive it.","If threads share the stream, synchronize close() against readers or signal readers to stop before closing.","Wrap the stream in a guarded object that tracks a closed flag and fails with a clear, own IllegalStateException on misuse."],"exampleFix":"// before\nin.close();\nlong finalPos = in.getPos(); // throws \"Stream is closed!\"\n\n// after\nlong finalPos = in.getPos();\nin.close();","handlingStrategy":"validation","validationCode":"final class GuardedStream implements Closeable {\n  private final FSDataInputStream in;\n  private volatile boolean closed;\n  GuardedStream(FileSystem fs, Path p) throws IOException { in = fs.open(p); }\n  long pos() throws IOException {\n    if (closed) throw new IllegalStateException(\"getPos after close\");\n    return in.getPos();\n  }\n  @Override public void close() throws IOException { closed = true; in.close(); }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return in.getPos();\n} catch (IOException e) {\n  if (FSExceptionMessages.STREAM_IS_CLOSED.equals(e.getMessage())) {\n    throw new IllegalStateException(\"stream used after close\", e); // lifecycle bug: fail loudly\n  }\n  throw e;\n}","preventionTips":["Use try-with-resources so close ordering is structural, not manual","Capture final positions/counters before close()","Give each stream one owner; stop background threads before closing","Never retry reads on a stream that an error handler already closed - reopen instead"],"tags":["hadoop","filesystem","io","stream-lifecycle","use-after-close"],"backgroundTag":"stream-closed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}