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

  1. Give every inode a unique <id> that no other inode uses and that does not exceed <lastInodeId>
  2. Regenerate the dump instead of cloning entries; if cloning is required, assign fresh sequential ids
  3. 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

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


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