apache/hadoop · error · InvalidXmlException

expecting </EDITS>

Error message

expecting </EDITS>

What it means

When offlineEditsViewer reads an XML edits file (-p xml input or XmlEditsVisitors round-trip), OfflineEditsXmlLoader drives a SAX handler as a strict state machine. endDocument() must find the machine in ParseState.EXPECT_END, reached only after the closing </EDITS> tag has been consumed with a well-formed record sequence. Any other final state throws InvalidXmlException('expecting </EDITS>') — in practice the document ended early, most often a truncated file cut off before the closing tag.

Source

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

    } finally {
      fileReader.close();
    }
  }
  
  @Override
  public void startDocument() {
    state = ParseState.EXPECT_EDITS_TAG;
    stanza = null;
    stanzaStack = new Stack<Stanza>();
    opCode = null;
    cbuf = new StringBuilder();
    nextTxId = -1;
  }
  
  @Override
  public void endDocument() {
    if (state != ParseState.EXPECT_END) {
      throw new InvalidXmlException("expecting </EDITS>");
    }
  }
  
  @Override
  public void startElement (String uri, String name,
      String qName, Attributes atts) {
    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 " +

View on GitHub (pinned to 2add963021)

Solutions

  1. Re-generate the XML from the source binary edits log with 'hdfs oev -i <edits> -o out.xml -p xml' rather than repairing by hand.
  2. If the source is gone, restore the tail (at minimum a well-formed sequence of closed records plus </EDITS>) from a backup or snapshot of the XML.
  3. Sanity-check the file first: 'tail -n 5 file.xml' should show </EDITS>, and xmllint --noout reports where well-formedness breaks.

Example fix

<!-- before: file ends abruptly -->
<RECORD><OPCODE>9</OPCODE><DATA>...unbalanced...

<!-- after: complete document -->
<EDITS><EDITS_VERSION>-64</EDITS_VERSION>
  <RECORD><OPCODE>9</OPCODE><DATA>...</DATA></RECORD>
</EDITS>
Defensive patterns

Strategy: try-catch

Validate before calling

// Cheap structural pre-check before handing the file to oev
List<String> tail = Files.readAllLines(Path.of(file)).size() > 5
    ? Files.readAllLines(Path.of(file)).subList(
        Files.readAllLines(Path.of(file)).size() - 5,
        Files.readAllLines(Path.of(file)).size()) : List.of();
if (tail.stream().noneMatch(l -> l.trim().equals("</EDITS>"))) {
  throw new IOException(file + " does not end with </EDITS>; likely truncated");
}

Try / catch

try {
  OfflineEditsLoader loader = OfflineEditsLoader.createLoader(visitor);
  loader.loadEdits();
} catch (InvalidXmlException e) {
  // SAX-state failure: message names what the machine expected
  System.err.println("Edits XML malformed: " + e.getMessage()
      + " - regenerate with 'hdfs oev -p xml' from the binary edits");
}

Prevention

When it happens

Trigger: Feeding oev an edits XML file that is truncated (missing or unclosed </EDITS>), or one whose records stopped mid-structure, e.g. partial copy from a crashed scp, log rotation artifact, or manual editing that deleted the tail.

Common situations: Copying a large edits XML over a flaky link and getting a short file; regenerating XML by concatenation that dropped the last line; hand-trimming files for test fixtures.

Related errors


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