apache/hadoop · error · IOException
this stream is already closed
Error message
this stream is already closed
What it means
CachingBlockManager.get(blockNumber) re-checks the manager's closed flag on every iteration of its retry loop; if the owning prefetch stream was closed while get() is still running (typically from another thread), it aborts with IOException("this stream is already closed") rather than returning data.
Source
Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/impl/prefetch/CachingBlockManager.java:156
/**
* Gets the block having the given {@code blockNumber}.
*
* @throws IllegalArgumentException if blockNumber is negative.
*/
@Override
public BufferData get(int blockNumber) throws IOException {
checkNotNegative(blockNumber, "blockNumber");
BufferData data;
final int maxRetryDelayMs = bufferPoolSize * 120 * 1000;
final int statusUpdateDelayMs = 120 * 1000;
Retryer retryer = new Retryer(10, maxRetryDelayMs, statusUpdateDelayMs);
boolean done;
do {
if (closed) {
throw new IOException("this stream is already closed");
}
data = bufferPool.acquire(blockNumber);
done = getInternal(data);
if (retryer.updateStatus()) {
LOG.warn("waiting to get block: {}", blockNumber);
LOG.info("state = {}", this.toString());
}
}
while (!done && retryer.continueRetry());
if (done) {
return data;
} else {
String message = String.format("Wait failed for get(%d)", blockNumber);
throw new IllegalStateException(message);
}View on GitHub (pinned to 2add963021)
Solutions
- Give the stream a single owner: only the owner closes, and only after readers finish
- In cancellation paths, signal readers to stop and join them before closing
- Treat this IOException in reader threads as a cancellation signal, not a data error
- Open a separate stream per thread instead of sharing one
Example fix
// before
new Thread(() -> { try { in.read(); } catch (IOException e) { /* ... */ } }).start();
in.close(); // racing reader -> "this stream is already closed"
// after
Thread reader = new Thread(() -> { try { in.read(); } catch (IOException e) { /* ... */ } });
reader.start();
reader.join(); // reader finished before close
in.close(); Defensive patterns
Strategy: try-catch
Try / catch
in reader threads, catch IOException with message "this stream is already closed" and interpret it as cancellation/shutdown — exit the reader cleanly instead of reporting a data error.
Prevention
- Single owner closes the stream, and only after readers finish (join them)
- In cancellation paths, signal readers before closing inputs
- Open one stream per thread rather than sharing
When it happens
Trigger: One thread closes the prefetch input stream while another is blocked in read()/get() waiting for a block; task cancellation closing inputs mid-read; watchdog code closing "stuck" streams that are merely waiting on a slow block fetch.
Common situations: Sharing one stream across threads without a close handshake; MR/Spark task-kill paths closing inputs while reader threads drain; timeout-driven cleanup racing legitimate slow reads.
Related errors
- Wait failed for acquire(%d)
- Stream is closed!
- Null IO stream
- Interrupted while copying objects (copy)
- Task set failed with an uncaught throwable
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/ee7b70c452565360.
Report an issue: GitHub.