stanfordnlp/CoreNLP · error · IllegalArgumentException
Required a tree with CoreLabels
Error message
Required a tree with CoreLabels
What it means
SentimentPipeline.setSentimentLabels recursively annotates a tree with predicted sentiment classes and requires every node's Label to be an instance of CoreLabel. If any node carries a plain StringLabel/LabeledWord or another Label implementation, the cast would be unsafe, so an IllegalArgumentException is thrown instead. This is an input precondition failure: the tree given to the pipeline is not backed by the expected label type.
Solutions
- Ensure the input trees go through a pipeline (StanfordCoreNLP tokenize/parse) that produces CoreLabel-backed nodes before sentiment labeling.
- If reading trees from text, re-label them, e.g. with a TreeNormalizer/TreeTransformer that replaces each node label with a CoreLabel carrying the same value.
- Check which TreeReader/parser model was used; switch to one configured with CoreLabel factory (e.g. via ParserOptions/parser props).
- As a last resort, convert labels manually: clone the tree and for each node setLabel(new CoreLabel()) copying the original value before calling the pipeline.
Example fix
// before
Tree t = Tree.valueOf("(ROOT (S (NP I) (VP (V like) (NP it))))");
SentimentPipeline.setSentimentLabels(t); // StringLabel nodes -> IllegalArgumentException
// after
Tree read = treeReader.readTree(...); // reader configured with CoreLabel factory
// or rebuild labels:
for (Tree node : t) {
CoreLabel cl = new CoreLabel();
cl.setValue(node.label().value());
node.setLabel(cl);
} Defensive patterns
Strategy: type-guard
Validate before calling
boolean hasCoreLabels(Tree t) {
for (Tree node : t) {
if (!(node.label() instanceof CoreLabel)) return false;
}
return true;
}
// call before pipeline: if (!hasCoreLabels(tree)) rebuildLabels(tree); Type guard
static boolean isCoreLabelTree(Tree t) {
if (t == null || !(t.label() instanceof CoreLabel)) return false;
for (Tree child : t.children()) {
if (!isCoreLabelTree(child)) return false;
}
return true;
} Try / catch
try {
SentimentPipeline.setSentimentLabels(tree);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("CoreLabels")) {
tree = relabelAsCoreLabels(tree); // fallback conversion
SentimentPipeline.setSentimentLabels(tree);
} else throw e;
} Prevention
- Always obtain trees from a StanfordCoreNLP/lexparser setup configured for CoreLabel output.
- Write a unit test asserting every node label of your input trees is a CoreLabel.
- When reading trees from text, apply a relabeling TreeTransformer immediately after parsing.
- Avoid mixing trees from different parser versions/configurations in one pipeline.
When it happens
Trigger: Calling setSentimentLabels (directly or via outputTree in SentimentPipeline) with a Tree whose nodes were built by a parser or TreeReader that produces StringLabel or other non-CoreLabel Label implementations instead of CoreLabel.
Common situations: Loading trees from a plain-text .mrg/.tree file with a generic TreeReader; combining trees produced by an older parser setup with the sentiment model; programmatically constructing trees with Tree.valueOf() without forcing CoreLabel backing; swapping tokenizer/parser props so downstream trees lose CoreLabel annotation.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Expected a tree
- Stack should have CoreLabel nodes
- Expected tree labels to be CoreLabel
- Only operates on CoreLabels
- addFeature was called with a features object that is neither
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/a1b901b96ec0ccd9.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/sentiment/SentimentPipeline.java:81
private SentimentPipeline() {} // static methods
/**
* Sets the labels on the tree (except the leaves) to be the integer
* value of the sentiment prediction. Makes it easy to print out
* with Tree.toString()
*/
private static void setSentimentLabels(Tree tree) {
if (tree.isLeaf()) {
return;
}
for (Tree child : tree.children()) {
setSentimentLabels(child);
}
Label label = tree.label();
if (!(label instanceof CoreLabel)) {
throw new IllegalArgumentException("Required a tree with CoreLabels");
}
CoreLabel cl = (CoreLabel) label;
cl.setValue(Integer.toString(RNNCoreAnnotations.getPredictedClass(tree)));
}
/**
* Sets the labels on the tree to be the indices of the nodes.
* Starts counting at the root and does a postorder traversal.
*/
private static int setIndexLabels(Tree tree, int index) {
if (tree.isLeaf()) {
return index;
}
tree.label().setValue(Integer.toString(index));
index++;
for (Tree child : tree.children()) {
index = setIndexLabels(child, index);View on GitHub (pinned to 1b7edd19c4)