stanfordnlp/CoreNLP · error · IllegalArgumentException

Called headPreTerminal on a leaf:

Error message

Called headPreTerminal on a leaf: 

What it means

headPreTerminal(HeadFinder) walks down from a node to its head preterminal (the head's parent of leaf). If called on a leaf node there is no preterminal below it, so the method throws IllegalArgumentException including the offending tree in the message.

Solutions

  1. Guard with isPreTerminal() or !isLeaf() before calling headPreTerminal
  2. Use a different accessor (e.g. headTerminal(hf) or the node itself) when starting from a leaf
  3. Fix HeadFinder rules if determineHead is returning leaves instead of preterminals

Example fix

// before
Tree p = node.headPreTerminal(hf);
// after
if (!node.isLeaf()) { Tree p = node.headPreTerminal(hf); } else { Tree p = node; }
Defensive patterns

Strategy: type-guard

Validate before calling

if (node.isLeaf()) throw new IllegalStateException("headPreTerminal is undefined for leaves");

Type guard

Tree headPreTerminalSafe(Tree t, HeadFinder hf) { return t.isLeaf() ? t : (t.isPreTerminal() ? t : t.headPreTerminal(hf)); }

Try / catch

try { return node.headPreTerminal(hf); } catch (IllegalArgumentException e) { log.warn("leaf passed to headPreTerminal"); return node; }

Prevention

When it happens

Trigger: Calling tree.headPreTerminal(headFinder) directly on a leaf Tree, or recursion reaching a leaf whose head path bottoms out at a leaf (e.g. determineHead returns a child that is itself a leaf).

Common situations: Feature-extraction loops that iterate all nodes including leaves and call headPreTerminal on each; head-finder rules misconfigured so heads resolve to leaves rather than preterminals.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/trees/Tree.java:1139

    return headTerminal(hf, null);
  }


  /**
   * Returns the preterminal tree that is the head of the tree.
   * See {@link #isPreTerminal()} for
   * the definition of a preterminal node. Beware that some tree nodes may
   * have no preterminal head.
   *
   * @param hf The headfinding algorithm to use
   * @return The head preterminal tree, if any, else {@code null}
   * @throws IllegalArgumentException if called on a leaf node
   */
  public Tree headPreTerminal(HeadFinder hf) {
    if (isPreTerminal()) {
      return this;
    } else if (isLeaf()) {
      throw new IllegalArgumentException("Called headPreTerminal on a leaf: " + this);
    } else {
      Tree head = hf.determineHead(this);
      if (head != null) {
        return head.headPreTerminal(hf);
      }
      log.info("Head preterminal is null: " + this);
      return null;
    }
  }

  /**
   * Finds the head words of each tree and assigns
   * HeadWordLabelAnnotation on each node pointing to the correct
   * CoreLabel.  This relies on the nodes being CoreLabels, so it
   * throws an IllegalArgumentException if this is ever not true.
   */
  public void percolateHeadAnnotations(HeadFinder hf) {
    if (!(label() instanceof CoreLabel)) {

View on GitHub (pinned to 1b7edd19c4)