stanfordnlp/CoreNLP · error · IllegalStateException
Classes derived from AbstractCollinsHeadFinder must create…
Error message
Classes derived from AbstractCollinsHeadFinder must create and fill HashMap nonTerminalInfo.
What it means
AbstractCollinsHeadFinder.determineHead requires the subclass to have populated the nonTerminalInfo map defining head rules per nonterminal category; if it is null the head finder is unconfigured and IllegalStateException is thrown. It catches subclasses that never initialized their grammar-specific rules.
Solutions
- Initialize nonTerminalInfo = new HashMap<>() in the subclass constructor and populate rules for every relevant nonterminal category (percolate default rules via super)
- Reuse an existing configured head finder (e.g. CollinsHeadFinder, SemanticHeadFinder) instead of a bare subclass
- Add a unit test that calls determineHead on a small tree to fail fast at construction time
- If subclassing, call a shared init method from every constructor
Example fix
// before
public MyHeadFinder(TreebankLanguagePack tlp) {
super(tlp);
}
// after
public MyHeadFinder(TreebankLanguagePack tlp) {
super(tlp);
nonTerminalInfo = new HashMap<>();
nonTerminalInfo.put("S", new String[][] {{"left", "NP", "VP"}});
nonTerminalInfo.put("default", new String[][] {{"right", "NN"}});
} Defensive patterns
Strategy: validation
Validate before calling
Field f = AbstractCollinsHeadFinder.class.getDeclaredField("nonTerminalInfo"); f.setAccessible(true); if (f.get(headFinder) == null) { throw new IllegalStateException("head finder not initialized"); } Type guard
boolean isConfigured(HeadFinder hf) { return hf instanceof AbstractCollinsHeadFinder && nonTerminalInfoInitialized((AbstractCollinsHeadFinder) hf); } Try / catch
try { Tree head = headFinder.determineHead(tree); } catch (IllegalStateException e) { log.error("head finder subclass missing nonTerminalInfo rules"); } Prevention
- Populate nonTerminalInfo in every constructor of a custom head finder
- Prefer extending/configured built-ins like CollinsHeadFinder or SemanticHeadFinder
- Add a smoke test that determines heads of a sample tree at startup
When it happens
Trigger: Instantiating a subclass of AbstractCollinsHeadFinder whose constructor did not create and fill nonTerminalInfo (e.g. writing a custom head finder without defining rules), then calling determineHead / percolateHeads.
Common situations: Custom head finder implementations for a new treebank or language that forgot rule definitions; subclasses constructed via reflection where the initializing constructor was bypassed.
Related errors
- Error initializing FeatureExtractorRunner
- RuntimeException wrapping Exception (dataset read failure)
- need to do training first!
- Cannot process tree
- Don't know anything about tagset
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/f878bb555102cf4d.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/trees/AbstractCollinsHeadFinder.java:161
public Tree determineHead(Tree t) {
return determineHead(t, null);
}
/**
* 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;View on GitHub (pinned to 1b7edd19c4)