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
- Check Thread.currentThread().isInterrupted() when this IOException appears: if set, treat it as cancellation instead of retrying.
- Ensure one stream per thread; never share an FSDataInputStream.
- Tune read-ahead settings (fs.cosn.read.ahead.queue.size, read-ahead executor size) if saturation recurs.
- 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
- Never share an FSDataInputStream between threads
- Handle task cancellation before interrupting reader threads
- Persist the last good getPos() so reads can resume after reopen
- Size fs.cosn.read.ahead.queue.size and the read-ahead pool for your fan-out
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
- Cannot seek to a negative offset
- Attempted to seek or read past the end of the file
- Interrupted while running disk check
- Invalid read parameters: buf.length=%d, off=%d, len=%d
- Cannot seek to a negative offset " + targetPos
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/9e4b926ab932c090.
Report an issue: GitHub.