apache/hadoop · error · InvalidXmlException

expected a <DATA> tag

Error message

expected a <DATA> tag

What it means

After <OPCODE> closes, the loader is in ParseState.EXPECT_DATA and the next element must be <DATA>, which opens the stanza tree holding the operation's fields. Any other element there throws InvalidXmlException('expected a <DATA> tag'), and the parse aborts before the record can be converted.

Source

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

        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();
      stanzaStack.push(parent);
      stanza = child;
      parent.addChild(name, child);
      break;
    case EXPECT_END:
      throw new InvalidXmlException("not expecting anything after </EDITS>");
    }
  }
  
  @Override
  public void endElement (String uri, String name, String qName) {

View on GitHub (pinned to 2add963021)

Solutions

  1. Ensure every <RECORD> has exactly the pair <OPCODE> then <DATA> (DATA may hold nested stanza children).
  2. For opcodes with no fields, keep an empty <DATA></DATA> element as emitted by oev itself.
  3. Regenerate or copy the record from an authentic XML dump of the same opcode.

Example fix

<!-- before -->
<RECORD><OPCODE>9</OPCODE><OPCODE>9</OPCODE></RECORD>

<!-- after -->
<RECORD><OPCODE>9</OPCODE><DATA><TXID>1</TXID></DATA></RECORD>
Defensive patterns

Strategy: validation

Validate before calling

// Inside each RECORD, second child must be DATA
try (XMLStreamReader r = XMLInputFactory.newFactory()
        .createXMLStreamReader(new FileInputStream(file))) {
  while (r.hasNext()) {
    int ev = r.next();
    if (ev == XMLStreamConstants.START_ELEMENT
        && "RECORD".equals(r.getLocalName())) {
      r.nextTag();                          // OPCODE
      r.nextTag();                          // must be DATA
      if (!"DATA".equals(r.getLocalName())) {
        throw new IOException("Expected <DATA> after <OPCODE>, found <"
            + r.getLocalName() + ">");
      }
    }
  }
}

Try / catch

try {
  loader.loadEdits();
} catch (InvalidXmlException e) {
  if (e.getMessage().contains("<DATA>")) {
    throw new IOException("Each <RECORD> needs an <OPCODE> followed by a "
        + "<DATA> block (empty allowed). " + e.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: A <RECORD> containing only an OPCODE (DATA removed), a duplicated OPCODE element instead of DATA, or an arbitrary child element inserted between OPCODE and DATA.

Common situations: Fixtures trimmed down to minimal records that accidentally dropped DATA; record merging that concatenated two OPCODEs; template-based generators emitting the wrong child name.

Related errors


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