stanfordnlp/CoreNLP · error · RuntimeException
Tree is not properly binary
Error message
Tree <treeNum> is not properly binary
What it means
OutputSubtrees extracts subtrees from a treebank and, when ASSERT_BINARY is enabled (set via -assertBinary), requires every input tree to be strictly binary (each internal node has exactly two children). This guard throws a RuntimeException identifying the 1-based tree number of the first non-binary tree.
Solutions
- Binarize the trees before processing, e.g. with TreeBinarizer (boundaryGenerator) or by running the trees through a parser that binarizes.
- Remove the -assertBinary flag if strict binary structure is not actually required, letting n-ary subtrees pass through.
- Locate the offending tree (message gives the 1-based number) and inspect/repair its structure.
- Ensure consistent preprocessing across all treebank files in the input path.
Example fix
// before
for (Tree t : treebank) { outputSubtrees(t); }
// after
TreeBinarizer bin = TreeBinarizer.boundaryFactories? -> use:
TreeBinarizer bin = TreeBinarizer.buildSimpleBinarizer("HEAD", "-TMP", false, false, false, op, false, 1.0, 0, tlpp.getBasicCategoryFunction(), false);
for (Tree t : treebank) { outputSubtrees(bin.transformTree(t)); } Defensive patterns
Strategy: validation
Validate before calling
// Verify binary-ness before running OutputSubtrees
treebank.forEach(t -> {
for (Tree n : t) {
if (!n.isLeaf() && n.numChildren() != 2)
throw new IllegalArgumentException("Non-binary node found: " + n.value());
}
}); Try / catch
try {
OutputSubtrees.main(args);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().endsWith("is not properly binary")) {
log.error(e.getMessage() + " — binarize input with TreeBinarizer first");
} else throw e;
} Prevention
- Always run trees through TreeBinarizer (or a parser's binarization) before binary-structure tools.
- Apply the same preprocessing to every treebank file in a mixed corpus.
- Omit -assertBinary when you intend to process unbinarized trees.
When it happens
Trigger: Running OutputSubtrees.main with -assertBinary=true on a treebank containing flat/n-ary constituents (e.g. raw Penn Treebank trees with 3+ children under a node, or unary chains mishandled), typically when the trees were not passed through TreeBinarizer first.
Common situations: Feeding the original Penn Treebank (unbinarized) trees directly; using the wrong binarization options for the downstream model; concatenating treebanks where some files were binarized and others not.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- : missing tag for
- ancestor: height cannot be negative
- Bad tree state:
- BinaryHeadFinder: unexpected tree:
- Can only operate on preterminals
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/cd20226292cd049c.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/trees/OutputSubtrees.java:92
} else {
remap = Collections.emptyMap();
}
MemoryTreebank treebank = new MemoryTreebank("utf-8");
treebank.loadPath(INPUT, null);
final Writer output;
if (OUTPUT == null) {
output = IOUtils.encodedOutputStreamWriter(System.out, "utf-8");
} else {
output = IOUtils.getPrintWriter(OUTPUT, "utf-8");
}
int treeNum = 0;
for (Tree tree : treebank) {
++treeNum;
if (ASSERT_BINARY && !tree.isBinary()) {
throw new RuntimeException("Tree " + treeNum + " is not properly binary");
}
//System.out.println(tree);
//System.out.println("--------------");
Iterable<Tree> subtrees = (ROOT_ONLY) ? Collections.singletonList(tree) : tree;
for (Tree subtree : subtrees) {
if (subtree.isLeaf()) {
continue;
}
String value = subtree.label().value();
List<Tree> leaves = Trees.leaves(subtree);
List<Label> labels = leaves.stream().map(x -> x.label()).collect(Collectors.toList());
String text = SentenceUtils.listToString(labels);
if (ignored.contains(value)) {
continue;
}
if (remap.containsKey(value)) {
value = remap.get(value);
}View on GitHub (pinned to 1b7edd19c4)