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

  1. Own the stream in exactly one place and use try-with-resources so reads cannot happen after close
  2. Null out the reference after close and check it before each use
  3. Coordinate concurrent close/read with a single owner thread or an external lock
  4. 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

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


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