{"record":{"id":"c4c56c4af362e64b","repo":"apache/hadoop","slug":"stream-closed-c4c56c","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/CryptoOutputStream.java","lineNumber":279,"sourceCode":"   */\n  @Override\n  public synchronized void flush() throws IOException {\n    if (closed) {\n      return;\n    }\n    encrypt();\n    super.flush();\n  }\n  \n  @Override\n  public void write(int b) throws IOException {\n    oneByteBuf[0] = (byte)(b & 0xff);\n    write(oneByteBuf, 0, oneByteBuf.length);\n  }\n  \n  private void checkStream() throws IOException {\n    if (closed) {\n      throw new IOException(\"Stream closed\");\n    }\n  }\n  \n  @Override\n  public void setDropBehind(Boolean dropCache) throws IOException,\n      UnsupportedOperationException {\n    try {\n      ((CanSetDropBehind) out).setDropBehind(dropCache);\n    } catch (ClassCastException e) {\n      throw new UnsupportedOperationException(\"This stream does not \" +\n          \"support setting the drop-behind caching.\");\n    }\n  }\n\n  @Override\n  public void hflush() throws IOException {\n    flush();\n    if (out instanceof Syncable) {","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/CryptoOutputStream.java#L261-L297","documentation":"CryptoOutputStream.checkStream() guards write and flush paths; after close() set closed = true (buffers and codec already returned/freed), any write()/flush() throws IOException(\"Stream closed\") immediately. This prevents writes into freed direct buffers or a closed cipher.","triggerScenarios":"write()/flush() after close() on a CryptoOutputStream; a producer thread writing while an error/timeout handler closes the stream concurrently; frameworks closing a sink on failure and then retrying writes to the same handle.","commonSituations":"Producer-consumer pipelines where a bad record closes the output while another thread is mid-write; sinks closed on timeout with queued writers unaware; double-close followed by reuse in wrapper streams.","solutions":["Close exactly once from the owning component, after all writers finish (drain-then-close ordering)","Wrap the whole write session in try-with-resources","Signal writers (flag/countdown latch) to stop before closing on error paths","On error recovery, open a new stream instead of reusing the closed one"],"exampleFix":"// before\nCryptoOutputStream out = ...;\ntry {\n  out.write(data);\n} finally {\n  out.close();\n}\nout.flush(); // IOException: Stream closed\n\n// after\ntry (CryptoOutputStream out = ...) {\n  out.write(data);\n  out.flush();\n} // single close, no post-close use","handlingStrategy":"validation","validationCode":"// No public isClosed() on CryptoOutputStream; gate writers with an owned flag.\nprivate final AtomicBoolean closed = new AtomicBoolean(false);\n\nvoid write(byte[] data) throws IOException {\n  if (closed.get()) {\n    throw new IllegalStateException(\"writer already closed\");\n  }\n  out.write(data);\n}\n\nvoid close() throws IOException {\n  if (closed.compareAndSet(false, true)) { out.close(); }\n}","typeGuard":null,"tryCatchPattern":"try {\n  out.write(data);\n} catch (IOException e) {\n  if (\"Stream closed\".equals(e.getMessage())) {\n    // stream was closed under us (timeout/error handler): reopen or fail cleanly\n    throw new IllegalStateException(\"write after close\", e);\n  }\n  throw e;\n}","preventionTips":["Establish drain-then-close ordering: stop producer threads before closing the sink","Use try-with-resources around the full write session","On error paths, signal writers via a flag/latch before closing the stream","After any close, open a new stream for retries instead of reusing the handle"],"tags":["crypto","stream","lifecycle","concurrency","hadoop"],"backgroundTag":"stream-already-closed","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}