stanfordnlp/CoreNLP · error · RuntimeException

Unmatched NE labels in MUC file

Error message

Unmatched NE labels in MUC file: {ner} v. {ner1}

What it means

nextDoc parses MUC-format SGML documents token by token; when it closes a named-entity tag it compares the closing label with the currently open one and throws RuntimeException("Unmatched NE labels in MUC file: X v. Y") on mismatch. It means the MUC file's NE SGML tags are nested or malformed — an opening tag was left unclosed or closed with the wrong name.

Solutions

  1. Fix the MUC file so every NE open tag is closed by the matching close tag with proper nesting
  2. Re-generate the MUC file from a reliable source/converter
  3. Check for stray/typo'd close tags (e.g. </ORGANISATION> vs </ORGANIZATION>)
  4. Pre-validate SGML tag balance before feeding the file to the mention extractor

Example fix

// before
<ORGANIZATION>Apple <PERSON>Tim Cook</ORGANIZATION></PERSON> <!-- bad nesting -->
// after
<ORGANIZATION>Apple</ORGANIZATION> <PERSON>Tim Cook</PERSON>
Defensive patterns

Strategy: validation

Validate before calling

// check NE tag balance before feeding a MUC file to MUCMentionExtractor
Deque<String> stack = new ArrayDeque<>();
Matcher m = Pattern.compile("</?([A-Z]+)>").matcher(mucFileText);
while (m.find()) {
    if (m.group(0).startsWith("</")) {
        if (stack.isEmpty() || !stack.pop().equals(m.group(1))) {
            throw new IllegalStateException("Unmatched NE tag: " + m.group(0));
        }
    } else {
        stack.push(m.group(1));
    }
}

Try / catch

try {
    extractor.nextDoc();
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unmatched NE labels")) {
        log.error("Malformed MUC SGML: " + e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: MUCMentionExtractor.nextDoc reads a MUC file where </SOMETHING> appears while a different <SOMETHING> tag is still open (e.g. <ORGANIZATION> ... </PERSON>), or the tokenizer splits tags unexpectedly.

Common situations: Hand-edited or machine-generated MUC files with mismatched SGML tags, incorrectly nested NE markup, HTML-ish entities confusing the simple tokenizer, or files converted from another format with broken tags.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/588c1dd6e1873e31. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/dcoref/MUCMentionExtractor.java:177

              word.set(CoreAnnotations.NamedEntityTagAnnotation.class, "O");
            }
          }
          sentence.add(word);
        }
        // found the start SGML tag for a NE, e.g., "<ORGANIZATION>"
        else if (w.startsWith("<") && !w.startsWith("<COREF") && !w.startsWith("</")) {
          Pattern nerPattern = Pattern.compile("<(.*?)>");
          Matcher m = nerPattern.matcher(w);
          m.find();
          ner = m.group(1);
        }
        // found the end SGML tag for a NE, e.g., "</ORGANIZATION>"
        else if (w.startsWith("</") && !w.startsWith("</COREF")) {
          Pattern nerPattern = Pattern.compile("</(.*?)>");
          Matcher m = nerPattern.matcher(w);
          m.find();
          String ner1 = m.group(1);
          if (ner != null && !ner.equals(ner1)) throw new RuntimeException("Unmatched NE labels in MUC file: " + ner + " v. " + ner1);
          ner = null;
        }
        // found the start SGML tag for a coref mention
        else if (w.startsWith("<COREF")) {
          Mention mention = new Mention();
          // position of this mention in the sentence
          mention.startIndex = sentence.size();

          // extract GOLD info about this coref chain. needed for eval
          Pattern idPattern = Pattern.compile("ID=\"(.*?)\"");
          Pattern refPattern = Pattern.compile("REF=\"(.*?)\"");

          Matcher m = idPattern.matcher(w);
          m.find();
          mention.mentionID = Integer.parseInt(m.group(1));

          m = refPattern.matcher(w);
          if (m.find()) {

View on GitHub (pinned to 1b7edd19c4)