apache/hadoop · error · IOException

Stream closed

Error message

Stream closed

What it means

readWithStrategy() first calls dfsClient.checkOpen() and then tests the stream's closed flag; any read attempted after close() throws this IOException. It is a pure use-after-close lifecycle bug on the caller side (or a FileSystem closed underneath the stream), not a cluster condition.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs-client/src/main/java/org/apache/hadoop/hdfs/DFSInputStream.java:868

    String msg = String.format("Failed to read from all available datanodes for file %s "
        + "at position=%d after retrying.", src, position);
    DFSClient.LOG.error(msg);
    for (Map.Entry<InetSocketAddress, List<IOException>> dataNodeExceptions :
        exceptionMap.entrySet()) {
      List<IOException> exceptions = dataNodeExceptions.getValue();
      for (IOException ex : exceptions) {
        msg = String.format("Exception when fetching file %s at position=%d at datanode %s:", src,
            position, dataNodeExceptions.getKey());
        DFSClient.LOG.error(msg, ex);
      }
    }
  }

  protected synchronized int readWithStrategy(ReaderStrategy strategy)
      throws IOException {
    dfsClient.checkOpen();
    if (closed.get()) {
      throw new IOException("Stream closed");
    }

    int len = strategy.getTargetLength();
    CorruptedBlocks corruptedBlocks = new CorruptedBlocks();
    // A map to record IOExceptions when fetching from each datanode. Key is the socketAddress of
    // a datanode.
    Map<InetSocketAddress, List<IOException>> exceptionMap = new HashMap<>();
    failures = 0;

    maybeRegisterBlockRefresh();

    if (pos < getFileLength()) {
      int retries = 2;
      while (retries > 0) {
        try {
          // currentNode can be left as null if previous read had a checksum
          // error on the same block. See HDFS-3067
          if (pos > blockEnd || currentNode == null) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Own the stream in exactly one place; close it once, after all reads finish
  2. Use try-with-resources around the whole read lifetime, not around a producer that hands the stream out
  3. Do not close shared FileSystem instances (FileSystem.get caches per URI); use IOUtils.closeStream in finally on streams only

Example fix

// before
FSDataInputStream in = fs.open(path);
readHeader(in);
in.close();
readBody(in); // throws "Stream closed"

// after: keep the stream open for its whole use, close once
try (FSDataInputStream in = fs.open(path)) {
  readHeader(in);
  readBody(in);
}
Defensive patterns

Strategy: validation

Validate before calling

// one-owner wrapper that makes the lifecycle explicit at the call site
final class GuardedReader implements Closeable {
  private final FSDataInputStream in;
  private volatile boolean closed;
  GuardedReader(FileSystem fs, Path p) throws IOException { in = fs.open(p); }
  int read(byte[] b) throws IOException {
    if (closed) throw new IllegalStateException("reader closed");
    return in.read(b);
  }
  public synchronized void close() throws IOException {
    if (!closed) { closed = true; in.close(); }
  }
}

Type guard

static boolean isUseAfterClose(IOException e) {
  return e.getMessage() != null && e.getMessage().equals("Stream closed");
}

Try / catch

try {
  return in.read(buf);
} catch (IOException e) {
  if (isUseAfterClose(e)) throw new IllegalStateException("bug: read after close", e);
  throw e;
}

Prevention

When it happens

Trigger: Calling read() after close() on the same FSDataInputStream; a wrapper/decoder stream closing the underlying stream early; closing the shared FileSystem while cached streams are still being read (checkOpen also fires when the client is shut down).

Common situations: Two components sharing one stream where one closes it; try-with-resources nesting mistakes; frameworks caching FileSystem instances and closing them per-job instead of per-user/VM.

Related errors


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