{"record":{"id":"38cab15d6a497364","repo":"stanfordnlp/CoreNLP","slug":"coordination-node-must-have-at-least-2-children-38cab1","errorCode":null,"errorMessage":"Coordination node must have at least 2 children.","messagePattern":"Coordination node must have at least 2 children\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/trees/tregex/CoordinationPattern.java","lineNumber":20,"sourceCode":"\nimport edu.stanford.nlp.trees.HeadFinder;\nimport edu.stanford.nlp.trees.Tree;\nimport edu.stanford.nlp.util.VariableStrings;\n\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.IdentityHashMap;\nimport java.util.Map;\n\nclass CoordinationPattern extends TregexPattern {\n\n  private final boolean isConj;\n  private final List<TregexPattern> children;\n\n  /* if isConj is true, then it is an \"AND\" ; if it is false, it is an \"OR\".*/\n  public CoordinationPattern(List<TregexPattern> children, boolean isConj) {\n    if (children.size() < 2) {\n      throw new RuntimeException(\"Coordination node must have at least 2 children.\");\n    }\n    this.children = children;\n    this.isConj = isConj;\n    //    System.out.println(\"Made \" + (isConj ? \"and \" : \"or \") + \"node with \" + children.size() + \" children.\");\n  }\n\n  @Override\n  public List<TregexPattern> getChildren() {\n    return children;\n  }\n\n  @Override\n  public String localString() {\n    return (isConj ? \"and\" : \"or\");\n  }\n\n  @Override\n  public String toString() {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/trees/tregex/CoordinationPattern.java#L2-L38","documentation":"A tregex CoordinationPattern represents an AND/OR node over child patterns; a coordination with fewer than two children is meaningless, so the constructor throws RuntimeException. This is an internal invariant enforced when building patterns from parsed tregex expressions.","triggerScenarios":"Constructing new CoordinationPattern(list, conj) with a list of size 0 or 1, e.g. when programmatically building tregex patterns or when a parser bug yields a degenerate conjunction/disjunction.","commonSituations":"Custom code that composes TregexPattern objects programmatically; deserializing or rebuilding patterns from stored tregex strings with only one clause after filtering.","solutions":["Ensure the children list has at least 2 TregexPattern objects before constructing the node","If only one child remains, use the child pattern directly instead of wrapping it in a coordination","If no children remain, return a trivially-true pattern or skip constructing the node","Check pattern-parsing/filtering logic for clauses being dropped incorrectly"],"exampleFix":"// before\nreturn new CoordinationPattern(children, true); // children.size() == 1\n// after\nif (children.size() == 1) return children.get(0);\nreturn new CoordinationPattern(children, true);","handlingStrategy":"validation","validationCode":"if (children == null || children.size() < 2)\n  throw new IllegalArgumentException(\"CoordinationPattern needs >= 2 children, got \" + (children == null ? 0 : children.size()));","typeGuard":null,"tryCatchPattern":"try {\n  pattern = new CoordinationPattern(children, true);\n} catch (RuntimeException e) {\n  pattern = children.isEmpty() ? null : children.get(0); // degenerate case\n}","preventionTips":["Unwrap single-child lists into the child pattern instead of coordinating","Filter clauses before building the coordination, then re-check the count","Add unit tests for programmatic pattern construction with 0/1/2+ children"],"tags":["java","tregex","invariant","pattern-matching"],"backgroundTag":"internal-invariant-violation","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}