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

  1. Never hold or reuse inner range streams after the parent ObjectMultiRangeInputStream closed
  2. Route all reads through the owning stream rather than inner chunks
  3. 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

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


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/4f29af25064ae55e. Report an issue: GitHub.