apache/hadoop · error · EOFException

Could not find target position {}

Error message

Could not find target position {}

What it means

EOFException from fetchBlockAt(): the client asked the NameNode for located blocks covering 'offset' and got back null or an empty list. There is simply no block at that position from the NN's point of view - typically the offset is past the data the NN knows because the file shrank or the cached length is stale.

Source

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

    return fetchBlockAt(offset, 0, false); // don't use cache
  }

  /** Fetch a block from namenode and cache it */
  private LocatedBlock fetchBlockAt(long offset, long length, boolean useCache)
      throws IOException {
    maybeRegisterBlockRefresh();
    synchronized(infoLock) {
      int targetBlockIdx = locatedBlocks.findBlock(offset);
      if (targetBlockIdx < 0) { // block is not cached
        targetBlockIdx = LocatedBlocks.getInsertIndex(targetBlockIdx);
        useCache = false;
      }
      if (!useCache) { // fetch blocks
        final LocatedBlocks newBlocks = (length == 0)
            ? dfsClient.getLocatedBlocks(src, offset)
            : dfsClient.getLocatedBlocks(src, offset, length);
        if (newBlocks == null || newBlocks.locatedBlockCount() == 0) {
          throw new EOFException("Could not find target position " + offset);
        }
        // Update the LastLocatedBlock, if offset is for last block.
        if (offset >= locatedBlocks.getFileLength()) {
          setLocatedBlocksFields(newBlocks, getLastBlockLength(newBlocks));
          // After updating the locatedBlock, the block to which the offset belongs
          // should be researched like {@link DFSInputStream#getBlockAt(long)}.
          if (offset >= locatedBlocks.getFileLength()) {
            return locatedBlocks.getLastLocatedBlock();
          } else {
            targetBlockIdx = locatedBlocks.findBlock(offset);
            assert targetBlockIdx >= 0 && targetBlockIdx < locatedBlocks.locatedBlockCount();
          }
        } else {
          locatedBlocks.insertRange(targetBlockIdx,
              newBlocks.getLocatedBlocks());
        }
      }
      return locatedBlocks.get(targetBlockIdx);

View on GitHub (pinned to 2add963021)

Solutions

  1. Bounds-check offset against a freshly fetched file length before each read/seek
  2. Treat EOFException here as end-of-input in tail loops: re-stat the file and back off
  3. Avoid concurrent truncate of files being read, or re-open after truncate
Defensive patterns

Strategy: validation

Validate before calling

long len = fs.getFileStatus(path).getLen();
if (position >= len) {
  return; // nothing to read past EOF
}
int n = in.read(position, buf, 0, buf.length);

Type guard

static boolean isTargetPositionMissing(IOException e) {
  return e instanceof EOFException
      && e.getMessage() != null && e.getMessage().contains("Could not find target position");
}

Try / catch

try {
  /* read at offset */
} catch (EOFException e) {
  // file shrank or offset is past data known to the NN: re-stat and back off
  revalidateFileLengthAndReopen();
}

Prevention

When it happens

Trigger: Reading/seeking at an offset beyond the file's real extent after a concurrent truncate; offset computed from a cached locatedBlocks set that outlived a file replacement; reading at exactly EOF during refresh.

Common situations: Tail loops that cache file length and keep reading after a log file was truncated/rotated; readers surviving a file being replaced while holding stale metadata.

Related errors


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