stanfordnlp/CoreNLP · error · IllegalArgumentException

Can't return head of null or leaf Tree.

Error message

Can't return head of null or leaf Tree.

What it means

AbstractCollinsHeadFinder.determineHead computes the head child of a constituent using the nonTerminalInfo rule table. It refuses to operate on a null tree or a leaf (pre-terminal/word) node, because a head is only meaningful for a non-terminal with children. Throwing here signals a caller bug: head lookup was invoked on a node that can never have a head rule.

Solutions

  1. Check that the tree is non-null and non-leaf before calling determineHead: if (t != null && !t.isLeaf()) head = hf.determineHead(t, parent);
  2. Fix tree loading so leaves are always under pre-terminal (POS) nodes — trees from tokenized/leaf-attached sources must be re-bracketed.
  3. Verify the caller recursion only visits non-terminal children (t.children() of internal nodes).

Example fix

// before
Tree head = headFinder.determineHead(child, tree);
// after
if (child != null && !child.isLeaf()) {
  Tree head = headFinder.determineHead(child, tree);
}
Defensive patterns

Strategy: validation

Validate before calling

if (tree == null || tree.isLeaf()) { throw new IllegalArgumentException("determineHead requires a non-leaf tree"); }

Type guard

boolean hasHead(Tree t) { return t != null && !t.isLeaf() && t.children().length > 0; }

Try / catch

try { head = hf.determineHead(t, parent); } catch (IllegalArgumentException e) { head = null; /* leaf/null node: no head applies */ }

Prevention

When it happens

Trigger: Calling determineHead(t) or determineHead(t, parent) with t == null, or with a leaf Tree (t.isLeaf() true, e.g. a word node from a Tree whose leaves were not wrapped in pre-terminals).

Common situations: Tree transformation code that walks all children including leaves and calls determineHead on each; parsing a tree where leaves were attached directly instead of under POS pre-terminals; passing a null tree from a failed read or an empty parse result.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/trees/AbstractCollinsHeadFinder.java:164

  /**
   * Determine which daughter of the current parse tree is the head.
   *
   * @param t The parse tree to examine the daughters of.
   *          If this is a leaf, {@code null} is returned
   * @param parent The parent of t
   * @return The daughter parse tree that is the head of {@code t}.
   *   Returns null for leaf nodes.
   * @see Tree#percolateHeads(HeadFinder)
   *      for a routine to call this and spread heads throughout a tree
   */
  @Override
  public Tree determineHead(Tree t, Tree parent) {
    if (nonTerminalInfo == null) {
      throw new IllegalStateException("Classes derived from AbstractCollinsHeadFinder must create and fill HashMap nonTerminalInfo.");
    }
    if (t == null || t.isLeaf()) {
      throw new IllegalArgumentException("Can't return head of null or leaf Tree.");
    }
    if (DEBUG) {
      log.info("determineHead for " + t.value());
    }

    Tree[] kids = t.children();

    Tree theHead;
    // first check if subclass found explicitly marked head
    if ((theHead = findMarkedHead(t)) != null) {
      if (DEBUG) {
        log.info("Find marked head method returned " +
                           theHead.label() + " as head of " + t.label());
      }
      return theHead;
    }

    // if the node is a unary, then that kid must be the head

View on GitHub (pinned to 1b7edd19c4)