apache/hadoop · error · EOFException

No key-value to read

Error message

No key-value to read

What it means

Thrown by Scanner.checkKey() as EOFException when a key/value read is attempted while the scanner is at or past its end location (atEnd() true). Entry material is lazily loaded: getKey()/getValue() on Scanner.Entry trigger checkKey(), and if no record remains, "No key-value to read" is the result. It signals normal exhaustion surfaced at the wrong layer, not file corruption.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/file/tfile/TFile.java:1609

      }

      /**
       * Is cursor at the end location?
       * 
       * @return true if the cursor is at the end location.
       */
      public boolean atEnd() {
        return (currentLocation.compareTo(endLocation) >= 0);
      }

      /**
       * check whether we have already successfully obtained the key. It also
       * initializes the valueInputStream.
       */
      void checkKey() throws IOException {
        if (klen >= 0) return;
        if (atEnd()) {
          throw new EOFException("No key-value to read");
        }
        klen = -1;
        vlen = -1;
        valueChecked = false;

        klen = Utils.readVInt(blkReader);
        if (klen < 0 || klen > MAX_KEY_SIZE) {
          throw new IOException("Key length out of range: " + klen);
        }
        blkReader.readFully(keyBuffer, 0, klen);
        valueBufferInputStream.reset(blkReader);
        if (valueBufferInputStream.isLastChunk()) {
          vlen = valueBufferInputStream.getRemain();
        }
      }

      /**
       * Get an entry to access the key and value.

View on GitHub (pinned to 2add963021)

Solutions

  1. Follow the canonical loop: check the initial entry, then while (scanner.advance()) { read scanner.entry() }
  2. Guard every entry access with !scanner.atEnd()
  3. Treat EOFException from reads as end-of-scan and stop cleanly rather than retrying

Example fix

// before
do { process(scanner.entry().getKey()); } while (scanner.advance()); // EOF on empty range

// after
if (!scanner.atEnd()) {
  process(scanner.entry().getKey());
}
while (scanner.advance()) {
  process(scanner.entry().getKey());
}
Defensive patterns

Strategy: validation

Validate before calling

// Canonical exhaustion-safe scan loop
Scanner scanner = reader.createScanner();
if (!scanner.atEnd()) {
  consume(scanner.entry());
}
while (scanner.advance()) {
  consume(scanner.entry());
}

Try / catch

catch (EOFException e) {
  // "No key-value to read": scanner exhausted; treat as clean end-of-iteration, not an error
}

Prevention

When it happens

Trigger: Calling scanner.entry().getKey() or getValue() without a preceding successful advance(); accessing the entry after advance() returned false; using a scanner created over an empty range or after seekTo parked the cursor at the end.

Common situations: Do-while loops that read the entry before calling advance(); ignoring the boolean returned by Scanner.advance(); assuming a seek always lands on a record when it may park at end; empty TFiles or empty scanner ranges.

Related errors


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