{"record":{"id":"3a0fb7985c995ba5","repo":"apache/beam","slug":"stream-has-been-finished-can-not-write-any-more-data","errorCode":null,"errorMessage":"Stream has been finished. Can not write any more data.","messagePattern":"Stream has been finished\\. Can not write any more data\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/util/BufferedElementCountingOutputStream.java","lineNumber":142,"sourceCode":"    }\n    finished = true;\n  }\n\n  /**\n   * Marks that a new element is being output. This allows this output stream to use the buffer if\n   * it had previously overflowed marking the start of a new block of elements.\n   */\n  public void markElementStart() throws IOException {\n    if (finished) {\n      throw new IOException(\"Stream has been finished. Can not add any more elements.\");\n    }\n    count++;\n  }\n\n  @Override\n  public void write(int b) throws IOException {\n    if (finished) {\n      throw new IOException(\"Stream has been finished. Can not write any more data.\");\n    }\n    if (count == 0) {\n      os.write(b);\n      return;\n    }\n\n    if (buffer.hasRemaining()) {\n      buffer.put((byte) b);\n    } else {\n      outputBuffer();\n      os.write(b);\n    }\n  }\n\n  @Override\n  public void write(byte[] b, int off, int len) throws IOException {\n    if (finished) {\n      throw new IOException(\"Stream has been finished. Can not write any more data.\");","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/util/BufferedElementCountingOutputStream.java#L124-L160","documentation":"The single-byte write(int b) of BufferedElementCountingOutputStream refuses output once the stream has been finished, throwing IOException('Stream has been finished. Can not write any more data.'). This enforces one-shot usage semantics after finish() to prevent corrupt output blocks.","triggerScenarios":"Calling write(int) after finish() — for example writing trailing bytes after a flush-and-finish, or reusing a finished stream for a new element.","commonSituations":"Loop code that finishes the stream inside the loop then keeps writing; retry logic re-attempting writes on a closed stream; misordered cleanup where finish() is invoked before all payload bytes are emitted.","solutions":["Write all bytes before calling finish(); reorder so finish() is the last operation.","Instantiate a fresh BufferedElementCountingOutputStream for any data written after a finish.","Guard writes with an isFinished/finished flag or try-catch IOException to detect premature writes in wrapper code."],"exampleFix":"// before\nstream.write(headerByte);\nstream.finish();\nstream.write(trailerByte); // IOException\n// after\nstream.write(headerByte);\nstream.write(trailerByte);\nstream.finish();","handlingStrategy":"validation","validationCode":"if (stream.finished) throw new IllegalStateException(\"stream already finished\");","typeGuard":null,"tryCatchPattern":"try {\n  stream.write(b);\n} catch (IOException e) {\n  if (e.getMessage().contains(\"finished\")) { /* replace stream */ }\n}","preventionTips":["Order writes strictly before finish().","Guard against retry paths re-entering writes after finish.","Encapsulate the stream so only one component controls its lifecycle."],"tags":["java","apache-beam","io","stream"],"backgroundTag":"invalid-state-transition","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}