{"record":{"id":"508f86b29bdb1e50","repo":"apache/hadoop","slug":"stream-is-closed-508f86","errorCode":null,"errorMessage":"Stream is closed!","messagePattern":"Stream is closed!","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSDataBlocks.java","lineNumber":695,"sourceCode":"       * After the stream is closed, set the local reference to the byte buffer\n       * to null; this guarantees that future attempts to use stream methods\n       * will fail.\n       */\n      @Override\n      public synchronized void close() {\n        LOG.debug(\"ByteBufferInputStream.close() for {}\",\n            ByteBufferBlock.super.toString());\n        byteBuffer = null;\n      }\n\n      /**\n       * Verify that the stream is open.\n       *\n       * @throws IOException if the stream is closed\n       */\n      private void verifyOpen() throws IOException {\n        if (byteBuffer == null) {\n          throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);\n        }\n      }\n\n      public synchronized int read() {\n        if (available() > 0) {\n          return byteBuffer.get() & OBSCommonUtils.BYTE_TO_INT_MASK;\n        } else {\n          return -1;\n        }\n      }\n\n      @Override\n      public synchronized long skip(final long offset)\n          throws IOException {\n        verifyOpen();\n        long newPos = position() + offset;\n        if (newPos < 0) {\n          throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSDataBlocks.java#L677-L713","documentation":"ByteBufferInputStream (used by the bytebuffer block buffer for in-flight fast-upload data) tracks liveness by nulling its byteBuffer on close(); verifyOpen() throws IOException(FSExceptionMessages.STREAM_IS_CLOSED) whenever a read/skip/available call happens after that. It means the block's input stream was already closed — either explicitly, by the framework after a successful multipart commit, or after an abort — and code kept reading from it. The javadoc on the read path explicitly declares '@throws IOException if the stream is closed'.","triggerScenarios":"Calling read()/skip()/available() on a ByteBufferBlock-backed InputStream after close() was invoked; holding a reference to the block stream across the OBSBlockOutputStream close/commit lifecycle and reading from it afterwards; a finally block that closes the stream while another thread is still inside a read loop.","commonSituations":"Job code that caches FSDataInputStream objects past the owning stream's lifetime; double-close followed by reuse; hand-rolled input-stream wrappers that buffer reads ahead after the inner stream is closed by a timeout/abort path.","solutions":["Audit call sites to ensure no read/skip happens after close() — structure code so close() is the terminal operation in a finally block owned by one place only","Wrap usage in try-with-resources so the stream cannot outlive the reading scope","If a wrapper stream is involved, make its close() idempotent and prevent read forwarding once closed","Check for a preceding exception in logs: the connector may have aborted blocks (closing their streams) before your code touched them again"],"exampleFix":"// before\nInputStream in = block.getBlockData();\nint b = in.read(); // after commit -> IOException: Stream is closed!\nin.close();\n\n// after\ntry (InputStream in = block.getBlockData()) {\n  int b = in.read(); // always inside the open window\n}","handlingStrategy":"try-catch","validationCode":"if (in instanceof java.io.Closeable && !isClosed(in)) { /* no portable open-state probe; rely on ownership instead */ }","typeGuard":null,"tryCatchPattern":"try {\n  return blockStream.read();\n} catch (IOException e) {\n  if (FSExceptionMessages.STREAM_IS_CLOSED.equals(e.getMessage())) {\n    // stream already committed/closed: stop reading, do not retry with the same handle\n    return -1;\n  }\n  throw e;\n}","preventionTips":["Use try-with-resources so the stream cannot be read after its scope","Close streams in exactly one place (single owner)","Make wrapper streams' close() idempotent and stop forwarding reads once closed"],"tags":["stream-lifecycle","io","state-violation","hadoop-obs"],"backgroundTag":"io-stream-closed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}