stanfordnlp/CoreNLP · error · IllegalArgumentException
No head rule defined for
Error message
No head rule defined for
What it means
determineNonTrivialHead looks up a head rule for the node's category (motherCat) in the nonTerminalInfo map. If no rule exists for that category the finder cannot know which child is the head and throws, including the class name and a printed tree so the missing rule can be identified. Subclasses of AbstractCollinsHeadFinder must define rules for every non-terminal they will encounter.
Solutions
- Add a rule for the missing category in your head finder subclass's nonTerminalInfo map (or extend a subclass that already has it).
- Use a head finder matching your treebank (e.g. UniversalSemanticHeadFinder for non-English data).
- Normalize/strip categories before head lookup, or configure the treebank language pack so node values match the rule keys.
- Inspect the printed tree in the message to see the exact category and context that lacked a rule.
Example fix
// before (custom finder)
nonTerminalInfo = new HashMap<>();
nonTerminalInfo.put("S", new String[][]{{"left", "VP"}});
// after — add rule for the unhandled category
nonTerminalInfo.put("S", new String[][]{{"left", "VP"}});
nonTerminalInfo.put("SBAR", new String[][]{{"left", "IN", "SBAR"}}); Defensive patterns
Strategy: validation
Validate before calling
if (headFinder instanceof AbstractCollinsHeadFinder) { /* verify nonTerminalInfo covers your categories, or pre-check */ Set<String> cats = collectCategories(tree); assert rulesCover(cats); } Try / catch
try { head = hf.determineHead(t, parent); } catch (IllegalArgumentException e) { log.warn("No head rule for tree: {}", e.getMessage()); head = t.children()[0]; /* fallback: leftmost child */ } Prevention
- Register head rules for every category your treebank can produce
- Use the language-appropriate head finder subclass
- Log unknown categories and extend nonTerminalInfo proactively
When it happens
Trigger: Calling determineHead on a tree containing a category (motherCat) for which the head finder subclass registered no entry in nonTerminalInfo — e.g. a custom POS tag, a projected/edited node, or a category introduced by preprocessing.
Common situations: Using EnglishHeadFinder/semanticHeadFinder rules on non-English or non-PTB treebank data; custom tree transformations inserting new node labels (e.g. X, ARTIFICAL nodes); missing tgrep/label normalization causing uppercase/mismatched categories.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- attempt to get word when sentence and lattice are null!
- Bad number put into wordToNumber. Word is: \"" + input +…
- Bad number put into wordToNumber. Word is: \"" + curPart +…
- Can't return head of null or leaf Tree.
- CANNOT EVEN CREATE ARRAYS OF ORIGINAL SIZE!!
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/642339e1ddda640f.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/trees/AbstractCollinsHeadFinder.java:245
if (how == null) {
if (DEBUG) {
log.info("Warning: No rule found for " + motherCat +
" (first char: " + motherCat.charAt(0) + ')');
log.info("Known nonterms are: " + nonTerminalInfo.keySet());
}
if (defaultRule != null) {
if (DEBUG) {
log.info(" Using defaultRule");
}
return traverseLocate(kids, defaultRule, true);
} else {
// TreePrint because TreeGraphNode only prints the node number,
// doesn't print the tree structure
TreePrint printer = new TreePrint("penn");
StringWriter buffer = new StringWriter();
printer.printTree(t, new PrintWriter(buffer));
// TODO: we could get really fancy and define our own exception class to represent this
throw new IllegalArgumentException("No head rule defined for " + motherCat + " using " + this.getClass() + " in " + buffer);
}
}
for (int i = 0; i < how.length; i++) {
boolean lastResort = (i == how.length - 1);
theHead = traverseLocate(kids, how[i], lastResort);
if (theHead != null) {
break;
}
}
if (DEBUG) {
log.info(" Chose " + (theHead == null ? "null node": theHead.label()));
}
return theHead;
}
/**
* Attempt to locate head daughter tree from among daughters.
* Go through daughterTrees looking for things from or not in a set given byView on GitHub (pinned to 1b7edd19c4)