stanfordnlp/CoreNLP · error · IllegalArgumentException

Got a close tag </" + tag.name + "> which does not match…

Error message

Got a close tag </" + tag.name + "> which does not match any open tag

What it means

While tokenizing XML in process(), a closing tag </name> arrived when no tags were open. Since the XML is unbalanced, CleanXmlAnnotator throws IllegalArgumentException unless allowFlawedXml is true (in which case it just logs a warning).

Solutions

  1. Fix or regenerate the input so all XML tags are properly opened and closed.
  2. Set the allowFlawedXml option (clean.allowflawedxml=true) to tolerate unbalanced tags with warnings.
  3. Strip the stray close tags from the input before annotation.

Example fix

// before
props.setProperty("clean.allowflawedxml", "false");
// after
props.setProperty("clean.allowflawedxml", "true");
Defensive patterns

Strategy: validation

Validate before calling

if (countCloseWithoutOpen(xml)) { /* balance tags or enable allowFlawedXml */ props.setProperty("clean.allowflawedxml", "true"); }

Try / catch

try { pipeline.annotate(annotation); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Got a close tag")) { annotation = retryWithFlawedXmlAllowed(originalText); } else { throw e; } }

Prevention

When it happens

Trigger: Feeding text to the annotator (process / newTokens path) that contains a close tag with no matching open tag, e.g. "</p>" appearing before or without "<p>", with allowFlawedXml=false.

Common situations: Processing HTML/XML snippets or truncated documents where tags were stripped or the document starts mid-element; concatenated fragments where open tags were cut off.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/pipeline/CleanXmlAnnotator.java:863

      if (xmlTagMatcher == null)
        continue;

      if (tag.isSingleTag) {
        continue;
      }
      // at this point, we can't reuse the "currentTagSet" vector
      // any more, since the current tag set has changed
      currentTagSet = null;
      if (tag.isEndTag) {
        while (true) {
          if (enclosingTags.isEmpty()) {
            String mesg = "Got a close tag </" + tag.name + "> which does not match any open tag";
            if (allowFlawedXml) {
              log.warn(mesg);
              break;
            } else {
              throw new IllegalArgumentException(mesg);
            }
          }
          String lastTag = enclosingTags.pop();
          if (xmlTagMatcher.matcher(lastTag).matches()) {
            matchDepth--;
          }
          if (lastTag.equals(tag.name)) {
            break;
          }
          String mesg = "Mismatched tags: </" + tag.name + "> closed a <" + lastTag + "> tag.";
          if ( ! allowFlawedXml) {
            throw new IllegalArgumentException(mesg);
          } else {
            log.warn(mesg);
          }
        }
        if (matchDepth < 0) {
          // this should be impossible, since we already assert that

View on GitHub (pinned to 1b7edd19c4)