apache/hadoop · error · InvalidXmlException

expected a <RECORD> tag

Error message

expected a <RECORD> tag

What it means

Once the version element closes, the loader sits in ParseState.EXPECT_RECORD and each subsequent start element must be <RECORD> (or nothing until </EDITS>). Any other element at that position — stray tags between records, misplaced data elements, or a record child leaking outside its parent — throws InvalidXmlException('expected a <RECORD> tag').

Source

Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/offlineEditsViewer/OfflineEditsXmlLoader.java:153

    switch (state) {
    case EXPECT_EDITS_TAG:
      if (!name.equals("EDITS")) {
        throw new InvalidXmlException("you must put " +
            "<EDITS> at the top of the XML file! " +
            "Got tag " + name + " instead");
      }
      state = ParseState.EXPECT_VERSION;
      break;
    case EXPECT_VERSION:
      if (!name.equals("EDITS_VERSION")) {
        throw new InvalidXmlException("you must put " +
            "<EDITS_VERSION> at the top of the XML file! " +
            "Got tag " + name + " instead");
      }
      break;
    case EXPECT_RECORD:
      if (!name.equals("RECORD")) {
        throw new InvalidXmlException("expected a <RECORD> tag");
      }
      state = ParseState.EXPECT_OPCODE;
      break;
    case EXPECT_OPCODE:
      if (!name.equals("OPCODE")) {
        throw new InvalidXmlException("expected an <OPCODE> tag");
      }
      break;
    case EXPECT_DATA:
      if (!name.equals("DATA")) {
        throw new InvalidXmlException("expected a <DATA> tag");
      }
      stanza = new Stanza();
      state = ParseState.HANDLE_DATA;
      break;
    case HANDLE_DATA:
      Stanza parent = stanza;
      Stanza child = new Stanza();

View on GitHub (pinned to 2add963021)

Solutions

  1. Restructure so every child of <EDITS> after <EDITS_VERSION> is exactly <RECORD>...</RECORD>.
  2. Re-emit the document from the binary edits with oev instead of repairing nesting by hand.
  3. Validate against a known-good dump: diff the element sequence (xmllint --shell or a SAX trace) to find the first divergent tag.

Example fix

<!-- before -->
<EDITS><EDITS_VERSION>-64</EDITS_VERSION>
<DATA><TXID>1</TXID></DATA>
<RECORD>...</RECORD></EDITS>

<!-- after -->
<EDITS><EDITS_VERSION>-64</EDITS_VERSION>
<RECORD>...</RECORD></EDITS>
Defensive patterns

Strategy: try-catch

Validate before calling

// Structural walk: after EDITS_VERSION, every start element must be RECORD
try (XMLStreamReader r = XMLInputFactory.newFactory()
        .createXMLStreamReader(new FileInputStream(file))) {
  r.next(); r.nextTag();                 // EDITS
  r.nextTag();                           // EDITS_VERSION
  while (r.hasNext()) {
    int ev = r.next();
    if (ev == XMLStreamConstants.START_ELEMENT
        && !"RECORD".equals(r.getLocalName())) {
      throw new IOException("Expected <RECORD>, found <" + r.getLocalName() + ">");
    }
  }
}

Try / catch

try {
  loader.loadEdits();
} catch (InvalidXmlException e) {
  if (e.getMessage().contains("<RECORD>")) {
    System.err.println("Edits XML has a stray element between records: "
        + e.getMessage() + " - regenerate from binary edits");
  }
}

Prevention

When it happens

Trigger: An XML edits file containing an unexpected element between records: e.g. text-structural tags introduced by manual merging, a <DATA> block placed directly under <EDITS>, or duplicated/deeply nested record tags from a broken generator.

Common situations: Concatenating two edits XMLs and leaving duplicate or misplaced fragments; script-generated XML with wrong nesting; diff/patch repairs that reindented content into invalid positions.

Related errors


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