apache/hadoop · error · IOException

Expected tag end event for {expected}, but got: {ev}

Error message

Expected tag end event for {expected}, but got: {ev}

What it means

expectTagEnd calls expectTag(expected, true) and requires the returned event to be an END_ELEMENT; when a matching (or [...] -group) START_ELEMENT comes back instead, this IOException fires with the full event printed. Concretely it means the stream opened a new element where a close was required - e.g. an extra <inode> appears after the inode loop finished, at the expectTagEnd(INODE_SECTION_NAME) call at OfflineImageReconstructor.java:604.

Source

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

                " instead.");
          }
        }
        return ev;
      default:
        // Ignore other event types like comment, etc.
        if (LOG.isTraceEnabled()) {
          LOG.trace("Skipping XMLEvent of type " +
              ev.getEventType() + "(" +  ev + ")");
        }
        break;
      }
    }
  }

  private void expectTagEnd(String expected) throws IOException {
    XMLEvent ev = expectTag(expected, true);
    if (ev.getEventType() != XMLStreamConstants.END_ELEMENT) {
      throw new IOException("Expected tag end event for " + expected +
            ", but got: " + ev);
    }
    if (!expected.startsWith("[")) {
      String tag = ev.asEndElement().getName().getLocalPart();
      if (!tag.equals(expected)) {
        throw new IOException("Expected tag end event for " + expected +
        ", but got tag end event for " + tag);
      }
    }
  }

  private static class Node {
    private static final String EMPTY = "";
    HashMap<String, LinkedList<Node>> children;
    String val = EMPTY;

    void addChild(String key, Node node) {
      if (children == null) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Make counts agree: either add the missing </inode> closes or raise <numInodes> to the actual entry count
  2. Check pairing with xmllint --noout (unbalanced tags usually trip well-formedness first)
  3. Regenerate the dump and apply additions through a DOM tool that recomputes counts

Example fix

<!-- before: 3 entries but numInodes says 2 -->
<INodeSection><numInodes>2</numInodes>
  <inode>...</inode><inode>...</inode><inode>...</inode>
</INodeSection>

<!-- after -->
<INodeSection><numInodes>3</numInodes>
  <inode>...</inode><inode>...</inode><inode>...</inode>
</INodeSection>
Defensive patterns

Strategy: validation

Validate before calling

# No sibling may appear where the section close belongs: counts must agree exactly
declared=$(xmllint --xpath 'string(//INodeSection/numInodes)' fsimage.xml)
actual=$(xmllint --xpath 'count(//inode)' fsimage.xml)
[ "$declared" -eq "$actual" ] || { echo "fix numInodes ($declared) to match $actual entries"; exit 1; }

Prevention

When it happens

Trigger: More <inode> entries physically present than <numInodes> declares (loop exits, expectTagEnd immediately sees the next START_ELEMENT <inode>); a missing close tag so a sibling start arrives where the section close was expected.

Common situations: Appending cloned inodes to a dump without incrementing <numInodes>; automated inserts that append a full element instead of replacing one.

Related errors


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