stanfordnlp/CoreNLP · error · IllegalArgumentException

Expected tree labels to have their heads assigned. Failed…

Error message

Expected tree labels to have their heads assigned.  Failed at: <tree>

What it means

After confirming the labels are CoreLabel, createTransitionSequenceHelper() reads TreeCoreAnnotations.HeadWordLabelAnnotation from the node and both children to decide the binary transition direction. If any head annotation is null, the tree's heads were never assigned, and it throws this IllegalArgumentException including the offending tree in the message.

Solutions

  1. Run head finding on the binarized tree before generating transitions (same preprocessing as ShiftReduceParser training).
  2. Use the library's training entry point rather than calling createTransitionSequence directly on raw treebank trees.
  3. Programmatically assign heads: apply a HeadFinder and set TreeCoreAnnotations.HeadWordLabelAnnotation on each node.
  4. Check the tree printed in the exception to find the node missing its head.

Example fix

// before
List<Transition> trans = createTransitionSequence(tree, false, rootStates, null);
// after
TrainOptions opts = new TrainOptions();
List<Tree> prep = ShiftReduceParser.preprocessTrees(Collections.singletonList(tree), opts);
List<Transition> trans = createTransitionSequence(prep.get(0), false, rootStates, null);
Defensive patterns

Strategy: validation

Validate before calling

CoreLabel lbl = (CoreLabel) tree.label();
if (lbl.get(TreeCoreAnnotations.HeadWordLabelAnnotation.class) == null)
    throw new IllegalArgumentException("Run head-finding before generating transitions: " + tree);

Type guard

boolean hasHeadsAssigned(Tree t) {
    if (!(t.label() instanceof CoreLabel)) return false;
    if (((CoreLabel) t.label()).get(TreeCoreAnnotations.HeadWordLabelAnnotation.class) == null) return false;
    for (Tree c : t.children()) if (!hasHeadsAssigned(c)) return false;
    return true;
}

Try / catch

try {
    List<Transition> trans = CreateTransitionSequence.createTransitionSequence(tree, false, rootStates, null);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Expected tree labels to have their heads assigned")) {
        // apply head finding to the offending tree, then retry
    }
}

Prevention

When it happens

Trigger: Generating transition sequences from trees that skipped the head-finding step (e.g. no SemanticGraphHeadFinder/HeadFinder pass) — heads are null for the node or either child.

Common situations: Training pipelines that load trees from a treebank file but forget the 'head-finding' preprocessing the shift-reduce trainer normally applies, or trees reconstructed programmatically without head annotations.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/parser/shiftreduce/CreateTransitionSequence.java:84

      // This is the tricky part... need to decide if the binary
      // transition is a left or right transition.  This is done by
      // looking at the existing heads of this node and its two
      // children.  The expectation is that the tree already has heads
      // assigned; otherwise, exception is thrown
      if (!(tree.label() instanceof CoreLabel) || 
          !(tree.children()[0].label() instanceof CoreLabel) ||
          !(tree.children()[1].label() instanceof CoreLabel)) {
        throw new IllegalArgumentException("Expected tree labels to be CoreLabel");
      }
      CoreLabel label = (CoreLabel) tree.label();
      CoreLabel leftLabel = (CoreLabel) tree.children()[0].label();
      CoreLabel rightLabel = (CoreLabel) tree.children()[1].label();
      CoreLabel head = label.get(TreeCoreAnnotations.HeadWordLabelAnnotation.class);
      CoreLabel leftHead = leftLabel.get(TreeCoreAnnotations.HeadWordLabelAnnotation.class);
      CoreLabel rightHead = rightLabel.get(TreeCoreAnnotations.HeadWordLabelAnnotation.class);
      if (head == null || leftHead == null || rightHead == null) {
        throw new IllegalArgumentException("Expected tree labels to have their heads assigned.  Failed at: " + tree);
      }
      boolean isRoot = rootOnlyStates.contains(tree.label().value());
      if (head == leftHead) {
        transitions.add(new BinaryTransition(tree.label().value(), BinaryTransition.Side.LEFT, isRoot));
      } else if (head == rightHead) {
        transitions.add(new BinaryTransition(tree.label().value(), BinaryTransition.Side.RIGHT, isRoot));
      } else {
        throw new IllegalArgumentException("Heads were incorrectly assigned: tree's head is not matched to either the right or left head");
      }
    } else {
      throw new IllegalArgumentException("Expected a binarized tree");
    }
  }
}

View on GitHub (pinned to 1b7edd19c4)