stanfordnlp/CoreNLP · error · IllegalArgumentException

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

Error message

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

What it means

fromProtoFlattenedTree expects the first node of a FlattenedParseTree proto to be an Open marker. A CloseNode encountered with an empty stack means the node sequence began with a close, which cannot form a valid tree, so an IllegalArgumentException naming the proto is thrown.

Solutions

  1. Regenerate the proto with toFlattenedTree, which always emits Open as the first node.
  2. Validate the flattened node stream (starts with Open, balanced Open/Close) before deserializing.
  3. Catch IllegalArgumentException and treat the parse annotation as unavailable.

Example fix

// before
nodes = [close("ROOT"), ...]; // starts with Close -> throws
// after
nodes = [open(), label("ROOT"), ..., close()]; // must start with Open
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

try {
  tree = ProtobufAnnotationSerializer.fromProto(proto);
} catch (IllegalArgumentException e) {
  log.warn("Flattened tree does not start with Open: " + e.getMessage());
  tree = null;
}

Prevention

When it happens

Trigger: Deserializing a FlattenedParseTree proto whose first entry (or any entry with no matching open on the stack) is a CloseNode — typically from truncated protos or off-by-one writers that dropped the initial Open marker.

Common situations: Protos sliced incorrectly during streaming transport; custom serializers that emit leaf nodes as close-only entries without the opening marker.

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/e5b1762b0817920a. Report an issue: GitHub.

Appendix: source

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

    // 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 {
          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);

View on GitHub (pinned to 1b7edd19c4)