apache/hadoop · error · IOException
Only read diffs out of
Error message
Only read ${actualDiffs + 1} diffs out of ${expectedDiffs} What it means
While reading the <count>-declared <dirDiff> children of a <dirDiffEntry>, expectTag("dirDiff") failed before the declared number was consumed, and the cause is re-wrapped with this message. Note an off-by-one quirk: the message prints actualDiffs+1, i.e. one more than the number of diffs successfully read, because it counts the failed iteration. The true reason (wrong tag, premature end event, etc.) is in the chained cause.
Solutions
- Read the chained cause to see what the parser hit instead of <dirDiff>
- Make <count> equal the number of <dirDiff> elements actually present in that <dirDiffEntry> (mind the message's off-by-one when interpreting it)
- Restore any <dirDiff> entries that were deleted or truncated
- Pre-validate every <dirDiffEntry> with a streaming count check before reconstructing
Example fix
<!-- before: count says 3, entry holds 2 --> <dirDiffEntry><inodeId>16386</inodeId><count>3</count> <dirDiff>...</dirDiff><dirDiff>...</dirDiff> </dirDiffEntry> <!-- after --> <dirDiffEntry><inodeId>16386</inodeId><count>2</count> <dirDiff>...</dirDiff><dirDiff>...</dirDiff> </dirDiffEntry>
Defensive patterns
Strategy: validation
Validate before calling
# python: <count> must equal number of <dirDiff> children per dirDiffEntry
# (also guards the follow-on 'Only read N diffs' failure)
import xml.etree.ElementTree as ET
def validate(path):
for el in ET.iterparse(path, events=('end',)):
e = el if el.tag == 'dirDiffEntry' else None
if e is not None:
c = e.find('count')
if c is None or int(c.text) != len(e.findall('dirDiff')):
return False
return True Try / catch
# on 'Only read N diffs out of M' inspect the chained cause in stderr, # correct <count> or restore diffs, delete partial output, re-run
Prevention
- Interpret the message knowing it reports one MORE than actually read (off-by-one)
- Update <count> whenever diffs are added/removed
- Stream-validate all entries before ReverseXML
- Never resume from a partially written output image
When it happens
Trigger: <count> larger than the actual number of <dirDiff> elements in the entry, or a malformed <dirDiff> that makes the stream reader hit an unexpected event mid-loop; also entries truncated by line-based editing.
Common situations: Hand-edited entries where diffs were deleted without updating <count>; scripts that append <dirDiff> blocks but never recompute the count; copy-paste of diff blocks between entries.
Related errors
- was , but there were entries.
- Only read diffs out of
- contained no entry.
- contained no entry.
- Expected entry to have a field
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/9332a795244de241.
Report an issue: GitHub.
Appendix: source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/offlineImageViewer/OfflineImageReconstructor.java:1448
Long inodeId = dirDiffHeader.removeChildLong(
SNAPSHOT_DIFF_SECTION_INODE_ID);
if (inodeId == null) {
throw new IOException("<dirDiffEntry> contained no <inodeId> entry.");
}
headerBld.setInodeId(inodeId);
Integer expectedDiffs = dirDiffHeader.removeChildInt(
SNAPSHOT_DIFF_SECTION_COUNT);
if (expectedDiffs == null) {
throw new IOException("<dirDiffEntry> contained no <count> entry.");
}
headerBld.setNumOfDiff(expectedDiffs);
dirDiffHeader.verifyNoRemainingKeys("dirDiffEntry");
headerBld.build().writeDelimitedTo(out);
for (int actualDiffs = 0; actualDiffs < expectedDiffs; actualDiffs++) {
try {
expectTag(SNAPSHOT_DIFF_SECTION_DIR_DIFF, false);
} catch (IOException e) {
throw new IOException("Only read " + (actualDiffs + 1) +
" diffs out of " + expectedDiffs, e);
}
Node dirDiff = new Node();
loadNodeChildren(dirDiff, "dirDiff fields");
FsImageProto.SnapshotDiffSection.DirectoryDiff.Builder bld =
FsImageProto.SnapshotDiffSection.DirectoryDiff.newBuilder();
Integer snapshotId = dirDiff.removeChildInt(
SNAPSHOT_DIFF_SECTION_SNAPSHOT_ID);
if (snapshotId != null) {
bld.setSnapshotId(snapshotId);
}
Integer childrenSize = dirDiff.removeChildInt(
SNAPSHOT_DIFF_SECTION_CHILDREN_SIZE);
if (childrenSize == null) {
throw new IOException("Expected to find <childrenSize> in " +
"<dirDiff> section.");
}
bld.setIsSnapshotRoot(dirDiff.removeChildBool(View on GitHub (pinned to 2add963021)