stanfordnlp/CoreNLP · error · RuntimeException

Missing head tree for a mention!

Error message

Missing head tree for a mention!

What it means

DocumentPreprocessor.fillMentionInfo throws when a mention's contextParseTree exists but the leaf at m.headIndex is null (or out of bounds), so no head tree can be located. It signals a desynchronization between the mention's head index and its parse tree.

Solutions

  1. Verify the same tokenization/sentence split feeds both the parser and mention extraction (run parse before coref, no re-tokenization in between)
  2. Check that m.headIndex is within the parse tree's leaf count before constructing mentions
  3. Use CoreNLP's own parse annotator output rather than a substitute parser with different leaf conventions
  4. Regenerate annotations end-to-end on the current CoreNLP version
Defensive patterns

Strategy: validation

Validate before calling

int leaves = m.contextParseTree.getLeaves().size();
if (m.headIndex < 0 || m.headIndex >= leaves)
  throw new IllegalStateException("headIndex " + m.headIndex + " out of tree leaves [0," + leaves + ")");

Try / catch

try {
  preprocessor.preprocess(props, doc);
} catch (RuntimeException e) {
  if ("Missing head tree for a mention!".equals(e.getMessage())) {
    logger.severe("Parse tree / mention index mismatch; rebuild annotations end-to-end");
  } else throw e;
}

Prevention

When it happens

Trigger: fillMentionInfo (via initializeMentions) computing m.contextParseTree.getLeaves().get(m.headIndex) where headIndex exceeds the leaf count — mention indices computed against a different tokenization/tree than the attached parse.

Common situations: Mismatched sentence segmentation between parse and mentions; custom pipeline stages that re-tokenize after parsing; corrupted or truncated parse trees; third-party parsers producing fewer leaves than tokens.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/coref/data/DocumentPreprocessor.java:327

        m.sentNum = i;                    // sentNum

        IntTuple headPosition = new IntTuple(2);
        headPosition.set(0, i);
        headPosition.set(1, m.headIndex);
        doc.mentionheadPositions.put(headPosition, m);    // headPositions

        m.contextParseTree = sentence.get(TreeAnnotation.class);
//        m.sentenceWords = sentence.get(TokensAnnotation.class);
        m.basicDependency = sentence.get(BasicDependenciesAnnotation.class);
        m.enhancedDependency = sentence.get(SemanticGraphCoreAnnotations.EnhancedDependenciesAnnotation.class);
        if (m.enhancedDependency == null) {
          m.enhancedDependency = sentence.get(SemanticGraphCoreAnnotations.BasicDependenciesAnnotation.class);
        }

        // mentionSubTree (highest NP that has the same head) if constituency tree available
        if (m.contextParseTree != null) {
          Tree headTree = m.contextParseTree.getLeaves().get(m.headIndex);
          if (headTree == null) { throw new RuntimeException("Missing head tree for a mention!"); }
          Tree t = headTree;
          while ((t = t.parent(m.contextParseTree)) != null) {
            if (t.headTerminal(headFinder) == headTree && t.value().equals("NP")) {
              m.mentionSubTree = t;
            } else if(m.mentionSubTree != null){
              break;
            }
          }
          if (m.mentionSubTree == null) {
            m.mentionSubTree = headTree;
          }
        }

        m.process(dict, null, singletonPredictor);
      }
    }

View on GitHub (pinned to 1b7edd19c4)