apache/hadoop · error · IOException
Stream is closed!
Error message
Stream is closed!
What it means
ObjectRangeInputStream serves a single HTTP range of an object inside the multi-range reader. Once its plain boolean closed flag is set, any subsequent operation hits checkNotClosed() and throws IOException("Stream is closed!") (FSExceptionMessages.STREAM_IS_CLOSED). Unlike the outer stream it has no AtomicBoolean and no async close, but the semantics are identical: use-after-close.
Source
Thrown at hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/ObjectRangeInputStream.java:188
closeStream();
stream = openStream(nextPos, range.end() - nextPos);
}
private InputStream openStream(long offset, long limit) throws IOException {
return storage.get(objectKey, offset, limit).verifiedStream(checksum);
}
private void closeStream() throws IOException {
if (stream != null) {
stream.close();
}
stream = null;
}
private void checkNotClosed() throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
}
}
public boolean include(long pos) {
return range.include(pos);
}
public Range range() {
return range;
}
}
View on GitHub (pinned to 2add963021)
Solutions
- Never hold or reuse inner range streams after the parent ObjectMultiRangeInputStream closed
- Route all reads through the owning stream rather than inner chunks
- Catch and tolerate this IOException during cancellation/shutdown paths
Example fix
// before
ObjectRangeInputStream range = ...; // inner chunk stream
range.close();
range.read(buf); // IOException: Stream is closed!
// after: only the owner stream is used and closed
try (ObjectMultiRangeInputStream in = storage.openStream(...)) {
in.read(buf);
} Defensive patterns
Strategy: try-catch
Try / catch
try {
rangeStream.read(buf);
} catch (IOException e) {
if (FSExceptionMessages.STREAM_IS_CLOSED.equals(e.getMessage())) {
// inner range stream already closed by its owner: stop using it
return;
}
throw e;
} Prevention
- Never hold inner ObjectRangeInputStream instances beyond the parent reader's lifetime
- Route all reads through the owning multi-range stream
- Close streams exactly once, from one owner
When it happens
Trigger: Reading from an ObjectRangeInputStream after the enclosing reader (or a test) closed it; calling read past the range after closeStream() has swapped or cleared the underlying stream.
Common situations: Custom code or tests that extract and hold inner range streams; interleaved close/read when concurrent readers share range streams; eager close in unit tests.
Related errors
- Stream is closed!
- Cannot seek to a negative offset %s
- position is negative
- Failed to rename %s to %s
- Expected checksum is %s while actual checksum is %s
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/4f29af25064ae55e.
Report an issue: GitHub.