{"record":{"id":"11c0ffa2d5e977f8","repo":"apache/hadoop","slug":"stream-closed-11c0ff","errorCode":null,"errorMessage":"Stream closed","messagePattern":"Stream closed","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoInputStream.java","lineNumber":786,"sourceCode":"  @Override\n  public FileDescriptor getFileDescriptor() throws IOException {\n    if (in instanceof HasFileDescriptor) {\n      return ((HasFileDescriptor) in).getFileDescriptor();\n    } else if (in instanceof FileInputStream) {\n      return ((FileInputStream) in).getFD();\n    } else {\n      return null;\n    }\n  }\n  \n  @Override\n  public int read() throws IOException {\n    return (read(oneByteBuf, 0, 1) == -1) ? -1 : (oneByteBuf[0] & 0xff);\n  }\n  \n  private void checkStream() throws IOException {\n    if (closed) {\n      throw new IOException(\"Stream closed\");\n    }\n  }\n  \n  /** Get direct buffer from pool */\n  private ByteBuffer getBuffer() {\n    ByteBuffer buffer = bufferPool.poll();\n    if (buffer == null) {\n      buffer = ByteBuffer.allocateDirect(bufferSize);\n    }\n    \n    return buffer;\n  }\n  \n  /** Return direct buffer to pool */\n  private void returnBuffer(ByteBuffer buf) {\n    if (buf != null) {\n      buf.clear();\n      bufferPool.add(buf);","sourceCodeStart":768,"sourceCodeEnd":804,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoInputStream.java#L768-L804","documentation":"CryptoInputStream.checkStream() runs at the top of every read/seek/positioned operation; once close() has set closed = true (after freeing buffers and the codec), any subsequent operation throws IOException(\"Stream closed\"). The guard fails fast instead of touching freed native buffers/decryptors.","triggerScenarios":"read()/seek()/readFully() called after close(); concurrent close() from one thread while another thread is reading (checkStream passes, then close frees buffers mid-decrypt — a use-after-close race); wrapper layers forwarding operations after an inner close.","commonSituations":"Reader objects outliving their stream in file-handle caches or connection pools; an error/timeout handler closing the stream while a worker still reads; frameworks that close sinks on failure and then retry reads on the same handle.","solutions":["Use try-with-resources so the stream lifetime is lexical and single-owner","Null out the reference on close so later use fails at the owner with a clear NPE instead of deep in the stream","Coordinate close with an in-use latch or read lock so closes wait for outstanding reads","For shared access, wrap in a reference-counted handle that closes only when the last user finishes"],"exampleFix":"// before\nFSDataInputStream in = fs.open(path);\nprocess(in);\nin.close();\nreadMore(in); // IOException: Stream closed\n\n// after\ntry (FSDataInputStream in = fs.open(path)) {\n  process(in);\n  readMore(in);\n} // closed exactly once, no use after close","handlingStrategy":"validation","validationCode":"// No public isOpen()/isClosed() on CryptoInputStream; enforce ownership instead.\n// Owner-tracked guard:\nprivate FSDataInputStream in; // single owner, guarded by this\nsynchronized boolean isOpen() { return in != null; }\nsynchronized void closeQuietly() { IOUtils.closeStream(in); in = null; }","typeGuard":null,"tryCatchPattern":"try {\n  n = in.read(buf, off, len);\n} catch (IOException e) {\n  if (\"Stream closed\".equals(e.getMessage())) {\n    throw new IllegalStateException(\"read after close on \" + path, e);\n  }\n  throw e;\n}","preventionTips":["Open streams with try-with-resources so scope equals lifetime","Never share a stream across threads without an external close/read protocol","Null out references after close so misuse surfaces at the owner","Use reference counting for shared file handles; close only on final release"],"tags":["crypto","stream","lifecycle","concurrency","hadoop"],"backgroundTag":"stream-already-closed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}