apache/hadoop · error · IOException

Null IO stream

Error message

Null IO stream

What it means

After reopen() requests a read-ahead buffer and waits for it, a still-null this.buffer triggers IOException('Null IO stream'). The visible path to a null buffer is the wait loop's catch of InterruptedException, which only logs a warning and leaves buffer null; a failed or cancelled read-ahead task on the bounded executor has the same effect. The stream then has no data to serve at the current position.

Source

Thrown at hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNInputStream.java:233

    if (null != readBuffer) {
      readBuffer.lock();
      try {
        readBuffer.await(ReadBuffer.INIT);
        if (readBuffer.getStatus() == ReadBuffer.ERROR) {
          this.buffer = null;
        } else {
          this.buffer = readBuffer.getBuffer();
        }
      } catch (InterruptedException e) {
        LOG.warn("An interrupted exception occurred "
            + "when waiting a read buffer.");
      } finally {
        readBuffer.unLock();
      }
    }

    if (null == this.buffer) {
      throw new IOException("Null IO stream");
    }

    this.position = pos;
    this.partRemaining = partSize;
  }

  @Override
  public void seek(long pos) throws IOException {
    if (pos < 0) {
      throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);
    }
    if (pos > this.fileSize) {
      throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF);
    }

    if (this.position == pos) {
      return;
    }

View on GitHub (pinned to 2add963021)

Solutions

  1. Check Thread.currentThread().isInterrupted() when this IOException appears: if set, treat it as cancellation instead of retrying.
  2. Ensure one stream per thread; never share an FSDataInputStream.
  3. Tune read-ahead settings (fs.cosn.read.ahead.queue.size, read-ahead executor size) if saturation recurs.
  4. Recover by reopening the stream at the last known good position (saved getPos()) and retrying the read once.

Example fix

// before
int b = in.read(); // IOException: Null IO stream after task interruption

// after
long lastGood = in.getPos();
try {
  int b = in.read();
} catch (IOException e) {
  if (Thread.currentThread().isInterrupted()) { throw new InterruptedIOException('cancelled'); }
  in.close();
  in = fs.open(p);
  in.seek(lastGood);
  int b = in.read();
}
Defensive patterns

Strategy: retry

Type guard

static boolean isNullIoStream(IOException e) {
  return e.getMessage() != null && e.getMessage().contains('Null IO stream');
}

Try / catch

long lastGood = in.getPos();
try {
  int b = in.read();
} catch (IOException e) {
  if (!e.getMessage().contains('Null IO stream')) { throw e; }
  if (Thread.currentThread().isInterrupted()) {
    throw new InterruptedIOException('read cancelled');
  }
  in.close();
  in = fs.open(p);
  in.seek(lastGood);
  int b = in.read(); // single retry from last good position
}

Prevention

When it happens

Trigger: A reader thread blocked in read/seek being interrupted (MR/Spark task cancellation); read-ahead executor saturation or task rejection; concurrent use of one FSDataInputStream from multiple threads, which the stream does not support.

Common situations: Job tasks cancelled while reading from COSN; aggressive pools interrupting blocked IO threads; read-ahead queue/executor sized too small (fs.cosn.read.ahead.queue.size and related settings) under heavy fan-out.

Related errors


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