{"record":{"id":"9e4b926ab932c090","repo":"apache/hadoop","slug":"null-io-stream","errorCode":null,"errorMessage":"Null IO stream","messagePattern":"Null IO stream","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNInputStream.java","lineNumber":233,"sourceCode":"    if (null != readBuffer) {\n      readBuffer.lock();\n      try {\n        readBuffer.await(ReadBuffer.INIT);\n        if (readBuffer.getStatus() == ReadBuffer.ERROR) {\n          this.buffer = null;\n        } else {\n          this.buffer = readBuffer.getBuffer();\n        }\n      } catch (InterruptedException e) {\n        LOG.warn(\"An interrupted exception occurred \"\n            + \"when waiting a read buffer.\");\n      } finally {\n        readBuffer.unLock();\n      }\n    }\n\n    if (null == this.buffer) {\n      throw new IOException(\"Null IO stream\");\n    }\n\n    this.position = pos;\n    this.partRemaining = partSize;\n  }\n\n  @Override\n  public void seek(long pos) throws IOException {\n    if (pos < 0) {\n      throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);\n    }\n    if (pos > this.fileSize) {\n      throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF);\n    }\n\n    if (this.position == pos) {\n      return;\n    }","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/CosNInputStream.java#L215-L251","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nint b = in.read(); // IOException: Null IO stream after task interruption\n\n// after\nlong lastGood = in.getPos();\ntry {\n  int b = in.read();\n} catch (IOException e) {\n  if (Thread.currentThread().isInterrupted()) { throw new InterruptedIOException('cancelled'); }\n  in.close();\n  in = fs.open(p);\n  in.seek(lastGood);\n  int b = in.read();\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"static boolean isNullIoStream(IOException e) {\n  return e.getMessage() != null && e.getMessage().contains('Null IO stream');\n}","tryCatchPattern":"long lastGood = in.getPos();\ntry {\n  int b = in.read();\n} catch (IOException e) {\n  if (!e.getMessage().contains('Null IO stream')) { throw e; }\n  if (Thread.currentThread().isInterrupted()) {\n    throw new InterruptedIOException('read cancelled');\n  }\n  in.close();\n  in = fs.open(p);\n  in.seek(lastGood);\n  int b = in.read(); // single retry from last good position\n}","preventionTips":["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"],"tags":["cosn","hadoop","input-stream","read-ahead","interrupted","concurrency"],"backgroundTag":"interrupted-during-read","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}