apache/hadoop · error · IOException

Block InputStream has no FileChannel.

Error message

Block InputStream has no FileChannel.

What it means

Thrown by MemoryMappableBlockLoader.load() (MemoryMappableBlockLoader.java:77), the DRAM (mmap+mlock) loader for HDFS centralized caching, when blockIn.getChannel() returns null. As with the other loaders this is a defensive check - FileInputStream.getChannel() on a stock JDK never returns null - so the branch is effectively theoretical; the realistic failure modes of this loader are mmap/mlock failures (ulimits), which throw different errors.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/fsdataset/impl/MemoryMappableBlockLoader.java:77

   *                       start. The caller must close this.
   * @param metaIn         The meta file input stream. Should be positioned at
   *                       the start. The caller must close this.
   * @param blockFileName  The block file name, for logging purposes.
   * @param key            The extended block ID.
   *
   * @throws IOException   If mapping block to memory fails or checksum fails.

   * @return               The Mappable block.
   */
  @Override
  MappableBlock load(long length, FileInputStream blockIn,
      FileInputStream metaIn, String blockFileName, ExtendedBlockId key)
      throws IOException {
    MemoryMappedBlock mappableBlock = null;
    MappedByteBuffer mmap = null;
    try (FileChannel blockChannel = blockIn.getChannel()) {
      if (blockChannel == null) {
        throw new IOException("Block InputStream has no FileChannel.");
      }
      mmap = blockChannel.map(FileChannel.MapMode.READ_ONLY, 0, length);
      NativeIO.POSIX.getCacheManipulator().mlock(blockFileName, mmap, length);
      verifyChecksum(length, metaIn, blockChannel, blockFileName);
      mappableBlock = new MemoryMappedBlock(mmap, length);
    } finally {
      if (mappableBlock == null) {
        if (mmap != null) {
          NativeIO.POSIX.munmap(mmap); // unmapping also unlocks
        }
      }
    }
    return mappableBlock;
  }

  @Override
  public long getCacheUsed() {
    return memCacheStats.getCacheUsed();

View on GitHub (pinned to 2add963021)

Solutions

  1. Reproduce on a stock supported JDK; remove JVM agents/instrumentation and retest
  2. If it persists, capture the FileInputStream concrete class in the exception (getClass()) via a debug patch and file a Hadoop JIRA
  3. FsDatasetCache already marks the caching attempt failed and frees the reservation - no manual cleanup beyond retrying the directive is needed
Defensive patterns

Strategy: try-catch

Try / catch

try {
  mappableBlock = new MemoryMappableBlockLoader(...).load(
      length, blockIn, metaIn, blockFileName, key);
} catch (IOException e) {
  // load() already munmaps on failure in its finally; just report and let the cache retry
  LOG.warn("DRAM caching failed for {}: {}", key, e);
}

Prevention

When it happens

Trigger: A cache directive on a cluster with dfs.datanode.max.locked.memory configured, where blockIn is somehow not backed by a real file channel (custom/instrumented JDK, exotic filesystem returning unusable channels).

Common situations: Practically does not occur; if reported, look at JVM-level tampering (agents, patched JDK) rather than HDFS configuration.

Related errors


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