{"record":{"id":"e5b1762b0817920a","repo":"stanfordnlp/CoreNLP","slug":"tree-started-with-a-close-not-an-open-offending","errorCode":null,"errorMessage":"Tree started with a Close, not an Open!  Offending proto: ${proto}","messagePattern":"Tree started with a Close, not an Open!  Offending proto: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/pipeline/ProtobufAnnotationSerializer.java","lineNumber":2226,"sourceCode":"    // we do that in a stack.  as we finish a node, we add it to the\n    // appropriate parent and forget about it\n    for (CoreNLPProtos.FlattenedParseTree.Node next : proto.getNodesList()) {\n      if (finished != null) {\n        throw new IllegalArgumentException(\"Tree continued after it was already closed!  Offending proto: \" + proto);\n      }\n      if (next.hasOpenNode()) {\n        if (stack.size() > 0 && stack.peek().label() == null) {\n          throw new IllegalArgumentException(\"Tree added a child before a label was added to a node!  Offending proto: \" + proto);\n        }\n        LabeledScoredTreeNode newNode = new LabeledScoredTreeNode();\n        stack.push(newNode);\n        if (next.hasScore()) {\n          newNode.setScore(next.getScore());\n        }\n      } else if (next.hasCloseNode()) {\n        if (stack.size() == 0) {\n          // demand that the tree always start with an Open\n          throw new IllegalArgumentException(\"Tree started with a Close, not an Open!  Offending proto: \" + proto);\n        }\n        LabeledScoredTreeNode child = stack.pop();\n        if (stack.size() == 0) {\n          // Popped off the last node.  Guess we're done.\n          // We don't return yet so that we check that the\n          // iterator is finished first\n          finished = child;\n        } else {\n          LabeledScoredTreeNode parent = stack.peek();\n          // note: this is actually kind of slow if the tree is really wide,\n          // but hopefully that's not a common occurrence\n          // we could solve that by keeping a stack of list of children as well\n          parent.addChild(child);\n        }\n      } else {\n        if (stack.size() == 0) {\n          // demand that the tree always start with an Open\n          throw new IllegalArgumentException(\"Tree started with a label, not an Open!  Offending proto: \" + proto);","sourceCodeStart":2208,"sourceCodeEnd":2244,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/pipeline/ProtobufAnnotationSerializer.java#L2208-L2244","documentation":"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.","triggerScenarios":"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.","commonSituations":"Protos sliced incorrectly during streaming transport; custom serializers that emit leaf nodes as close-only entries without the opening marker.","solutions":["Regenerate the proto with toFlattenedTree, which always emits Open as the first node.","Validate the flattened node stream (starts with Open, balanced Open/Close) before deserializing.","Catch IllegalArgumentException and treat the parse annotation as unavailable."],"exampleFix":"// before\nnodes = [close(\"ROOT\"), ...]; // starts with Close -> throws\n// after\nnodes = [open(), label(\"ROOT\"), ..., close()]; // must start with Open","handlingStrategy":"validation","validationCode":"if (proto.getNodesCount() == 0 || !proto.getNodes(0).hasOpenNode()) {\n  throw new IllegalArgumentException(\"flattened tree proto must start with an Open node\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  tree = ProtobufAnnotationSerializer.fromProto(proto);\n} catch (IllegalArgumentException e) {\n  log.warn(\"Flattened tree does not start with Open: \" + e.getMessage());\n  tree = null;\n}","preventionTips":["Validate first node hasOpenNode() before deserializing","Regenerate protos with toFlattenedTree after any format change","Guard against proto truncation in transport (length-prefix frames)"],"tags":["serialization","protobuf","tree","malformed-input"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}