stanfordnlp/CoreNLP · error · RuntimeException
Found two roots for sentence " + sentence
Error message
Found two roots for sentence " + sentence
What it means
When converting the raw dataset format into Trees, ReadSentimentDataset expects exactly one node with parent pointer -1 (the root) per sentence. If the parent-pointer list contains two or more -1 entries, the converter cannot determine a single root and throws RuntimeException.
Solutions
- Inspect the sentence's parent-pointer lines and ensure exactly one has -1
- Re-extract or re-download the pristine Stanford Sentiment Treebank dataset
- Fix your preprocessing script so only the top node has parent -1
Example fix
// before (data) 0 -1 -1 // after (data) 0 -1 1
Defensive patterns
Strategy: validation
Validate before calling
long roots = parentPointers.stream().filter(p -> p == -1).count();
if (roots != 1) throw new IllegalArgumentException("Expected exactly 1 root, found " + roots); Try / catch
try { converter.main(args); } catch (RuntimeException e) { if (e.getMessage().contains("Found two roots")) { reportCorruptSentence(e); } else throw e; } Prevention
- Validate dataset files (one root per sentence) before conversion
- Never hand-edit SST data files; regenerate from source
- Checksum dataset archives after download
When it happens
Trigger: Parsing a corrupted or hand-edited sentence file in the sentiment dataset format where more than one line has parent index -1, or a bug in custom dataset generation producing disconnected components.
Common situations: Manually modified train.txt/dev.txt files, partial downloads that merged chunks of two sentences, or custom-preprocessed data with wrong parent indexing.
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/9e6bab5ddefe9dd0.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/sentiment/ReadSentimentDataset.java:242
Tree[] subtrees = new Tree[maxNode + 1];
for (int i = 0; i < sentence.size(); ++i) {
CoreLabel word = new CoreLabel();
word.setValue(sentence.get(i));
Tree leaf = new LabeledScoredTreeNode(word);
subtrees[i] = new LabeledScoredTreeNode(new CoreLabel());
subtrees[i].addChild(leaf);
}
for (int i = sentence.size(); i <= maxNode; ++i) {
subtrees[i] = new LabeledScoredTreeNode(new CoreLabel());
}
boolean[] connected = new boolean[maxNode + 1];
Tree root = null;
for (int index = 0; index < parentPointers.size(); ++index) {
if (parentPointers.get(index) == -1) {
if (root != null) {
throw new RuntimeException("Found two roots for sentence " + sentence);
}
root = subtrees[index];
} else {
// Walk up the tree structure to make sure that leftmost
// phrases are added first. Otherwise, if the numbers are
// inverted, we might get the right phrase added to a parent
// first, resulting in "case zero in this", for example,
// instead of "in this case zero"
// Note that because we keep track of which ones are already
// connected, we process this at most once per parent, so the
// overall construction time is still efficient.
connect(parentPointers, subtrees, connected, index);
}
}
for (int i = 0; i <= maxNode; ++i) {
List<Tree> leaves = subtrees[i].getLeaves();
List<String> words = CollectionUtils.transformAsList(leaves, TRANSFORM_TREE_TO_WORD);View on GitHub (pinned to 1b7edd19c4)