apache/hadoop · error · IOException

Only read {} diffs out of {}

Error message

Only read {} diffs out of {}

What it means

While reading the <count>-declared <fileDiff> children of a <fileDiffEntry>, expectTag("fileDiff") failed before the declared count was consumed; the cause is re-wrapped with this message. Like the dir-diff variant, the message prints actualDiffs+1 - one more than the diffs actually read - so interpret the number accordingly.

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/offlineImageViewer/OfflineImageReconstructor.java:1555

      Long inodeId = fileDiffHeader.removeChildLong(
          SNAPSHOT_DIFF_SECTION_INODE_ID);
      if (inodeId == null) {
        throw new IOException("<fileDiffEntry> contained no <inodeid> entry.");
      }
      headerBld.setInodeId(inodeId);
      Integer expectedDiffs = fileDiffHeader.removeChildInt(
          SNAPSHOT_DIFF_SECTION_COUNT);
      if (expectedDiffs == null) {
        throw new IOException("<fileDiffEntry> contained no <count> entry.");
      }
      headerBld.setNumOfDiff(expectedDiffs);
      fileDiffHeader.verifyNoRemainingKeys("fileDiffEntry");
      headerBld.build().writeDelimitedTo(out);
      for (int actualDiffs = 0; actualDiffs < expectedDiffs; actualDiffs++) {
        try {
          expectTag(SNAPSHOT_DIFF_SECTION_FILE_DIFF, false);
        } catch (IOException e) {
          throw new IOException("Only read " + (actualDiffs + 1) +
              " diffs out of " + expectedDiffs, e);
        }
        Node fileDiff = new Node();
        loadNodeChildren(fileDiff, "fileDiff fields");
        FsImageProto.SnapshotDiffSection.FileDiff.Builder bld =
            FsImageProto.SnapshotDiffSection.FileDiff.newBuilder();
        Integer snapshotId = fileDiff.removeChildInt(
            SNAPSHOT_DIFF_SECTION_SNAPSHOT_ID);
        if (snapshotId != null) {
          bld.setSnapshotId(snapshotId);
        }
        Long size = fileDiff.removeChildLong(
            SNAPSHOT_DIFF_SECTION_SIZE);
        if (size != null) {
          bld.setFileSize(size);
        }
        String name = fileDiff.removeChildStr(SECTION_NAME);
        if (name != null) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Read the chained cause for the underlying tag mismatch
  2. Set <count> to the actual number of <fileDiff> elements in that <fileDiffEntry>
  3. Restore any truncated or deleted <fileDiff> blocks
  4. Stream-validate count vs entries for every fileDiffEntry before reconstructing

Example fix

<!-- before: count says 2, one diff present -->
<fileDiffEntry><inodeId>16390</inodeId><count>2</count>
  <fileDiff>...</fileDiff>
</fileDiffEntry>
<!-- after -->
<fileDiffEntry><inodeId>16390</inodeId><count>1</count>
  <fileDiff>...</fileDiff>
</fileDiffEntry>
Defensive patterns

Strategy: validation

Validate before calling

# python: <count> must equal number of <fileDiff> children per fileDiffEntry
import xml.etree.ElementTree as ET

def validate(path):
    for ev, el in ET.iterparse(path, events=('end',)):
        if el.tag == 'fileDiffEntry':
            c = el.find('count')
            if c is None or int(c.text) != len(el.findall('fileDiff')):
                return False
    return True

Try / catch

# on 'Only read N diffs out of M' read the chained cause in stderr,
# fix count or restore diffs, remove partial output, re-run

Prevention

When it happens

Trigger: <count> greater than the number of <fileDiff> elements in the entry, or a malformed <fileDiff> that makes the reader hit an unexpected tag/end event mid-loop.

Common situations: Hand-edits deleting file diffs without updating <count>; scripts appending diffs without recounting; truncated entries from sed/awk surgery on huge XML.

Related errors


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