{"record":{"id":"3144d409ca5d85e8","repo":"apache/hadoop","slug":"stream-is-closed-3144d4","errorCode":null,"errorMessage":"Stream is closed!","messagePattern":"Stream is closed!","errorType":"validation","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsOutputStream.java","lineNumber":450,"sourceCode":"  public void write(final int byteVal) throws IOException {\n    write(new byte[]{(byte) (byteVal & 0xFF)});\n  }\n\n  /**\n   * Writes length bytes from the specified byte array starting at off to\n   * this output stream.\n   *\n   * @param data   the byte array to write.\n   * @param off the start off in the data.\n   * @param length the number of bytes to write.\n   * @throws IOException if an I/O error occurs. In particular, an IOException may be\n   *                     thrown if the output stream has been closed.\n   */\n  @Override\n  public synchronized void write(final byte[] data, final int off, final int length)\n      throws IOException {\n    if (closed) {\n      throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);\n    }\n    // validate if data is not null and index out of bounds.\n    DataBlocks.validateWriteArgs(data, off, length);\n    maybeThrowLastError();\n\n    if (off < 0 || length < 0 || length > data.length - off) {\n      throw new IndexOutOfBoundsException();\n    }\n\n    if (hasLease() && isLeaseFreed()) {\n      throw new PathIOException(path, ERR_WRITE_WITHOUT_LEASE);\n    }\n    if (length == 0) {\n      LOG.debug(\"No data to write, length is 0 for path: {}\", path);\n      return;\n    }\n\n    AbfsBlock block = createBlockIfNeeded(position);","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbfsOutputStream.java#L432-L468","documentation":"AbfsOutputStream.write(byte[], int, int) checks the closed flag first and throws IOException(\"Stream is closed!\") for any write attempted after close(). close() itself is idempotent (a second close returns immediately), but a post-close write is always rejected before argument validation or lease checks run.","triggerScenarios":"Writing to an FSDataOutputStream after its close()/try-with-resources ended; producer threads still enqueuing data while the consumer thread closed the stream on error; framework retry logic that writes a trailer after the finally block closed the stream.","commonSituations":"Multi-threaded writers where one thread's failure closes the stream and another thread's write then fails; commit/trailer hooks running after close; buffered wrapper classes flushing on close after the inner ABFS stream was closed first.","solutions":["Wrap the output stream so close() is the terminal operation — try-with-resources with no writes after the block","In multi-writer setups, coordinate: signal writers to stop BEFORE closing the stream","If data must be appended after close, open a new output stream in append mode (fs.append)"],"exampleFix":"// before\nout.close();\nout.write(trailer);   // IOException: Stream is closed!\n\n// after\nout.write(trailer);\nout.close();\n\n// or append later\ntry (FSDataOutputStream out2 = fs.append(path)) {\n  out2.write(trailer);\n}","handlingStrategy":"validation","validationCode":"// Own the lifecycle: no writes after close, ever\npublic class SafeWriter implements Closeable {\n  private final FSDataOutputStream out;\n  private boolean closed;\n  SafeWriter(FSDataOutputStream out) { this.out = out; }\n  public synchronized void write(byte[] b, int off, int len) throws IOException {\n    if (closed) throw new IllegalStateException(\"writer already closed\");\n    out.write(b, off, len);\n  }\n  public synchronized void close() throws IOException {\n    if (!closed) { closed = true; out.close(); }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  out.write(buf, 0, len);\n} catch (IOException e) {\n  if (FSExceptionMessages.STREAM_IS_CLOSED.equals(e.getMessage())) {\n    // writer bug: data written after close — reopen in append mode if needed\n  } else throw e;\n}","preventionTips":["Try-with-resources around the output stream; write everything before the block ends","In multi-threaded writers, stop all writer threads before closing the stream","To add data later, use fs.append(path) on a new stream"],"tags":["azure-blob","abfs","hadoop","stream-lifecycle","write","closed-stream"],"backgroundTag":"stream-closed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}