stanfordnlp/CoreNLP · error · IllegalArgumentException
Tree added a child before a label was added to a node! …
Error message
Tree added a child before a label was added to a node! Offending proto: ${proto} What it means
During fromProtoFlattenedTree reconstruction, an Open node marker may not be pushed onto the stack while the node on top of the stack still has no label — the flattened format requires label-before-children. Violating this ordering yields an IllegalArgumentException identifying the offending proto.
Solutions
- Build flattened trees with ProtobufAnnotationSerializer.toFlattenedTree so ordering is guaranteed.
- Reorder nodes so each Open node is immediately followed by its label node before any child Open.
- Catch IllegalArgumentException and log/replace the malformed parse annotation.
Example fix
// before (wrong order) b.addNodes(open(parent)); b.addNodes(open(child)); b.addNodes(label(parent)); // after b.addNodes(open(parent)); b.addNodes(label(parent)); b.addNodes(open(child));
Defensive patterns
Strategy: validation
Validate before calling
// every Open at depth>=1 must be preceded by a label for the parent
for (int i = 1; i < proto.getNodesCount(); i++) {
var prev = proto.getNodes(i - 1);
var cur = proto.getNodes(i);
if (cur.hasOpenNode() && prev.hasOpenNode()) {
throw new IllegalArgumentException("Open followed by Open without label at " + i);
}
} Try / catch
try {
tree = ProtobufAnnotationSerializer.fromProto(proto);
} catch (IllegalArgumentException e) {
log.warn("Bad node ordering in flattened tree: " + e.getMessage());
tree = null;
} Prevention
- Emit label immediately after each Open node before children
- Use toFlattenedTree instead of hand-building node lists
- Add a round-trip unit test: toFlattenedTree -> fromProto
When it happens
Trigger: Deserializing a FlattenedParseTree proto where an OpenNode entry appears before a label/value entry for the currently open parent node, e.g. a hand-built proto with nodes ordered Open, Open, label instead of Open, label, Open.
Common situations: Custom code constructing FlattenedParseTree protos directly instead of using toFlattenedTree; language-specific writers that emit children before the node label.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- Tree continued after it was already closed! Offending proto
- Tree started with a Close, not an Open! Offending proto
- Tree started with a label, not an Open! Offending proto
- Tree never finished! Offending proto
- Empty label not supported
AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10).
Data as JSON: /api/errors/1b946b397940fe9c.
Report an issue: GitHub.
Appendix: source
Thrown at src/edu/stanford/nlp/pipeline/ProtobufAnnotationSerializer.java:2216
if (proto.getNodesList().size() == 0) {
return null;
}
Stack<LabeledScoredTreeNode> stack = new Stack<>();
LabeledScoredTreeNode finished = null;
// The incoming data structure is basically a PTB formatted tree
// with openNode representing ( and closeNode representing )
// essentially we only need to keep track of the current node and
// all of its ancestors
// we do that in a stack. as we finish a node, we add it to the
// appropriate parent and forget about it
for (CoreNLPProtos.FlattenedParseTree.Node next : proto.getNodesList()) {
if (finished != null) {
throw new IllegalArgumentException("Tree continued after it was already closed! Offending proto: " + proto);
}
if (next.hasOpenNode()) {
if (stack.size() > 0 && stack.peek().label() == null) {
throw new IllegalArgumentException("Tree added a child before a label was added to a node! Offending proto: " + proto);
}
LabeledScoredTreeNode newNode = new LabeledScoredTreeNode();
stack.push(newNode);
if (next.hasScore()) {
newNode.setScore(next.getScore());
}
} else if (next.hasCloseNode()) {
if (stack.size() == 0) {
// demand that the tree always start with an Open
throw new IllegalArgumentException("Tree started with a Close, not an Open! Offending proto: " + proto);
}
LabeledScoredTreeNode child = stack.pop();
if (stack.size() == 0) {
// Popped off the last node. Guess we're done.
// We don't return yet so that we check that the
// iterator is finished first
finished = child;
} else {View on GitHub (pinned to 1b7edd19c4)