apache/beam · error · IOException
Stream has been finished. Can not write any more data.
Error message
Stream has been finished. Can not write any more data.
What it means
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.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/BufferedElementCountingOutputStream.java:142
}
finished = true;
}
/**
* Marks that a new element is being output. This allows this output stream to use the buffer if
* it had previously overflowed marking the start of a new block of elements.
*/
public void markElementStart() throws IOException {
if (finished) {
throw new IOException("Stream has been finished. Can not add any more elements.");
}
count++;
}
@Override
public void write(int b) throws IOException {
if (finished) {
throw new IOException("Stream has been finished. Can not write any more data.");
}
if (count == 0) {
os.write(b);
return;
}
if (buffer.hasRemaining()) {
buffer.put((byte) b);
} else {
outputBuffer();
os.write(b);
}
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (finished) {
throw new IOException("Stream has been finished. Can not write any more data.");View on GitHub (pinned to 12126d8942)
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.
Example fix
// before stream.write(headerByte); stream.finish(); stream.write(trailerByte); // IOException // after stream.write(headerByte); stream.write(trailerByte); stream.finish();
Defensive patterns
Strategy: validation
Validate before calling
if (stream.finished) throw new IllegalStateException("stream already finished"); Try / catch
try {
stream.write(b);
} catch (IOException e) {
if (e.getMessage().contains("finished")) { /* replace stream */ }
} Prevention
- Order writes strictly before finish().
- Guard against retry paths re-entering writes after finish.
- Encapsulate the stream so only one component controls its lifecycle.
When it happens
Trigger: Calling write(int) after finish() — for example writing trailing bytes after a flush-and-finish, or reusing a finished stream for a new element.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Stream has been finished. Can not add any more elements.
- Failed closing channel to %s
- Error determining if %s allows dynamic splitting
- File spec %s not found
- Error matching file spec %s: status %s
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/3a0fb7985c995ba5.
Report an issue: GitHub.