apache/hadoop · error · IOException
Stream is closed!
Error message
Stream is closed!
What it means
ObjectMultiRangeInputStream tracks closure with an AtomicBoolean; once close() has run, the read/seek/positioned-read paths funnel through checkNotClosed(), which throws IOException("Stream is closed!") from FSExceptionMessages.STREAM_IS_CLOSED. This is the standard Hadoop use-after-close guard for the multi-range object reader (which may also close its active range stream asynchronously via a thread pool).
Source
Thrown at hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/ObjectMultiRangeInputStream.java:206
stream.seek(nextPos);
}
}
private void closeStream(boolean asyncClose) throws IOException {
if (stream != null) {
if (asyncClose) {
final ObjectRangeInputStream streamToClose = stream;
threadPool.submit(() -> CommonUtils.runQuietly(streamToClose::close));
} else {
stream.close();
}
stream = null;
}
}
private void checkNotClosed() throws IOException {
if (closed.get()) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
}
}
@Override
public synchronized void close() throws IOException {
super.close();
if (closed.compareAndSet(false, true)) {
closeStream(false);
}
}
// for test
public long nextExpectPos() {
return currPos;
}
@Override
public synchronized int available() throws IOException {View on GitHub (pinned to 2add963021)
Solutions
- Own the stream in exactly one place and use try-with-resources so reads cannot happen after close
- Null out the reference after close and check it before each use
- Coordinate concurrent close/read with a single owner thread or an external lock
- During cancellation paths, treat 'Stream is closed!' as an expected benign signal rather than an error
Example fix
// before
FSDataInputStream in = fs.open(path);
// ... later, after in.close() somewhere
in.read(buf); // IOException: Stream is closed!
// after
try (FSDataInputStream in = fs.open(path)) {
in.read(buf);
} // reads cannot outlive the stream Defensive patterns
Strategy: try-catch
Try / catch
try {
in.read(buf);
} catch (IOException e) {
if (FSExceptionMessages.STREAM_IS_CLOSED.equals(e.getMessage())) {
// stream was closed (e.g. cancellation): stop reading, do not retry
return;
}
throw e;
} Prevention
- Use try-with-resources so reads cannot outlive the stream
- Keep single ownership; never share an FSDataInputStream across threads without coordination
- Null out references after close and check before use
- During cancellation, treat 'Stream is closed!' as expected
When it happens
Trigger: read(), seek(), or read(position, ...) invoked after close(); a cleanup path closing the stream while another thread still reads it; double usage from finally blocks or metric/log hooks that read after closing.
Common situations: Cleanup code in finally that closes the stream, followed by another component reading it; sharing one FSDataInputStream across tasks/threads without coordination; wrappers caching the inner stream beyond the owner's lifetime.
Related errors
- Stream is closed!
- Cannot seek to a negative offset %s
- position is negative
- Stream closed
- Stream is closed!
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/727bdbd7a67b076d.
Report an issue: GitHub.