{"record":{"id":"db1c635318d84285","repo":"apache/hadoop","slug":"s-stream-is-closed","errorCode":null,"errorMessage":"%s: Stream is closed!","messagePattern":"(.+?): Stream is closed!","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleHadoopFSInputStream.java","lineNumber":184,"sourceCode":"  }\n\n  @Override\n  public int available() throws IOException {\n    if (!channel.isOpen()) {\n      throw new ClosedChannelException();\n    }\n    return super.available();\n  }\n\n  /**\n   * Verify that the input stream is open. Non-blocking; this gives the last state of the volatile\n   * {@link #closed} field.\n   *\n   * @throws IOException if the connection is closed.\n   */\n  private void checkNotClosed() throws IOException {\n    if (closed) {\n      throw new IOException(gcsPath + \": \" + FSExceptionMessages.STREAM_IS_CLOSED);\n    }\n  }\n}\n","sourceCodeStart":166,"sourceCodeEnd":188,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleHadoopFSInputStream.java#L166-L188","documentation":"GoogleHadoopFSInputStream.checkNotClosed throws IOException(\"<path>: Stream is closed!\") when any read/seek/available call happens after close() set the volatile closed flag. It is a client-side lifecycle guard - the stream object still exists but refuses further I/O.","triggerScenarios":"Calling in.read(...), in.seek(...), or in.available() after in.close(); returning an FSDataInputStream from a method whose try-with-resources already closed it; a lazy consumer (iterator, Spark partition reader) outliving the producer's scope.","commonSituations":"Streams handed to frameworks that consume them lazily after the producer closed them; double-close followed by read in error-handling paths; wrapped streams where the outer wrapper is read after the inner one was closed.","solutions":["Scope every read inside the try-with-resources block that owns the stream.","If a consumer needs the data later, copy the bytes out (or re-open the stream) instead of reusing a closed one.","Audit wrapper streams so only the outermost owner closes, and no reads occur after that point."],"exampleFix":"// before\nFSDataInputStream in = fs.open(path);\nin.close();\nin.read(buffer); // IOException: <path>: Stream is closed!\n\n// after\ntry (FSDataInputStream in = fs.open(path)) {\n  in.read(buffer); // all reads inside the owning scope\n}","handlingStrategy":"validation","validationCode":"try (FSDataInputStream in = fs.open(path)) {\n  process(in); // every read, seek, available inside this scope\n}\n// never let `in` escape this block","typeGuard":null,"tryCatchPattern":"catch IOException where message endsWith(\": Stream is closed!\") - re-open the stream (fs.open) rather than retrying on the closed instance.","preventionTips":["Always open GCS input streams with try-with-resources; keep all reads in scope.","Do not return streams from methods that also close them.","With lazy consumers, copy the data or pass an opener (supplier) instead of the stream itself."],"tags":["stream","gcs","hadoop","lifecycle","io"],"backgroundTag":"stream-already-closed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}