apache/hadoop · error · IOException
<inode> found without <id>
Error message
<inode> found without <id>
What it means
After <type>, processINodeXml requires SECTION_ID (<id>) and stores it as the inode's protobuf id - the unique INodeId the NameNode assigned, bounded by <lastInodeId> in the section header. An entry without it cannot be placed in the namespace tree, so the tool fails fast.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/offlineImageViewer/OfflineImageReconstructor.java:620
loadNodeChildren(inode, "INode fields");
INodeSection.INode.Builder inodeBld = processINodeXml(inode);
inodeBld.build().writeDelimitedTo(out);
}
expectTagEnd(INODE_SECTION_NAME);
recordSectionLength(SectionName.INODE.name());
}
}
private INodeSection.INode.Builder processINodeXml(Node node)
throws IOException {
String type = node.removeChildStr(INODE_SECTION_TYPE);
if (type == null) {
throw new IOException("INode XML found with no <type> tag.");
}
INodeSection.INode.Builder inodeBld = INodeSection.INode.newBuilder();
Long id = node.removeChildLong(SECTION_ID);
if (id == null) {
throw new IOException("<inode> found without <id>");
}
inodeBld.setId(id);
String name = node.removeChildStr(SECTION_NAME);
if (name != null) {
inodeBld.setName(ByteString.copyFrom(name, StandardCharsets.UTF_8));
}
switch (type) {
case "FILE":
processFileXml(node, inodeBld);
break;
case "DIRECTORY":
processDirectoryXml(node, inodeBld);
break;
case "SYMLINK":
processSymlinkXml(node, inodeBld);
break;
default:
throw new IOException("INode XML found with unknown <type> " +View on GitHub (pinned to 2add963021)
Solutions
- Give every inode a unique <id> that no other inode uses and that does not exceed <lastInodeId>
- Regenerate the dump instead of cloning entries; if cloning is required, assign fresh sequential ids
- Sweep first: xmllint --xpath 'count(//inode[id])' must equal xmllint --xpath 'count(//inode)'
Example fix
<!-- before: cloned entry with id stripped --> <inode><name>part-00000-copy</name><type>FILE</type></inode> <!-- after --> <inode><id>16402</id><name>part-00000-copy</name><type>FILE</type></inode>
Defensive patterns
Strategy: validation
Validate before calling
total=$(xmllint --xpath 'count(//inode)' fsimage.xml)
withId=$(xmllint --xpath 'count(//inode[id])' fsimage.xml)
[ "$total" = "$withId" ] || { echo "$((total-withId)) <inode> entries missing <id>"; exit 1; }
# ids must also be unique and <= lastInodeId
xmllint --xpath '//inode/id/text()' fsimage.xml | tr ' ' '\n' | sort | uniq -d | grep -q . \
&& { echo 'duplicate inode ids found'; exit 1; } Prevention
- Assign fresh sequential ids when cloning inodes; never ship id-less entries
- Keep ids unique and bounded by <lastInodeId>
- Run the id-presence/uniqueness sweep before every ReverseXML run
When it happens
Trigger: ReverseXML where an <inode> element had its <id> child removed or renamed, or an entry was cloned to duplicate a file and the id stripped to 'make it unique' without assigning a new one.
Common situations: Cloning inodes by copy-paste to duplicate files; template-based hand authoring; filters that drop 'internal' fields.
Related errors
- INode XML found with no <type> tag.
- <NameSection> is missing <namespaceId>
- Failed to find <numInodes> in INodeSection.
- Expecting {expected}, but got XMLStreamException
- Got unexpected attribute: {ev}
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/ab2ac2e598eb5755.
Report an issue: GitHub.