stanfordnlp/CoreNLP · error · IllegalArgumentException

Tree started with a label, not an Open! Offending proto

Error message

Tree started with a label, not an Open!  Offending proto: ${proto}

What it means

In fromProtoFlattenedTree, a value/label node encountered while the stack is empty means the sequence started with a label rather than an Open marker. Since labels only make sense attached to an open node, the serializer throws an IllegalArgumentException identifying the proto.

Solutions

  1. Produce flattened trees exclusively via toFlattenedTree so the sequence starts with Open.
  2. Validate that the first node hasOpenNode() before calling the deserializer.
  3. Catch IllegalArgumentException and re-obtain the parse from the annotator.

Example fix

// before
nodes = [label("S"), open(), ..., close()]; // label before any Open -> throws
// after
nodes = [open(), label("S"), ..., close()];
Defensive patterns

Strategy: validation

Validate before calling

if (proto.getNodesCount() == 0 || !proto.getNodes(0).hasOpenNode()) {
  throw new IllegalArgumentException("flattened tree proto must begin with an Open node, not a label");
}

Try / catch

try {
  tree = ProtobufAnnotationSerializer.fromProto(proto);
} catch (IllegalArgumentException e) {
  log.warn("Label encountered outside an open node: " + e.getMessage());
  tree = null;
}

Prevention

When it happens

Trigger: Deserializing a FlattenedParseTree proto that begins with a value node, or that has a label node after all nodes have been closed — usually from protos built by hand or written by a non-conforming producer.

Common situations: Hand-rolled protobuf writers omitting the initial open marker; mixing node lists from different trees during transport or caching.

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


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/41165351cc256e61. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/pipeline/ProtobufAnnotationSerializer.java:2244

          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 {
          LabeledScoredTreeNode parent = stack.peek();
          // note: this is actually kind of slow if the tree is really wide,
          // but hopefully that's not a common occurrence
          // we could solve that by keeping a stack of list of children as well
          parent.addChild(child);
        }
      } else {
        if (stack.size() == 0) {
          // demand that the tree always start with an Open
          throw new IllegalArgumentException("Tree started with a label, not an Open!  Offending proto: " + proto);
        }
        LabeledScoredTreeNode top = stack.peek();
        if (top.label() == null) {
          // the first label after an Open is the label
          CoreLabel value = new CoreLabel();
          value.setCategory(next.getValue());
          value.setValue(next.getValue());
          top.setLabel(value);
          if (next.hasScore()) {
            top.setScore(next.getScore());
          }
        } else {
          // subsequence labels will be children
          LabeledScoredTreeNode child = new LabeledScoredTreeNode();
          CoreLabel value = new CoreLabel();
          value.setCategory(next.getValue());
          value.setValue(next.getValue());
          child.setLabel(value);

View on GitHub (pinned to 1b7edd19c4)