{"record":{"id":"57ed968d507bfc16","repo":"stanfordnlp/CoreNLP","slug":"only-the-root-node-can-produce-the-top-level-match","errorCode":null,"errorMessage":"Only the root node can produce the top level matcher","messagePattern":"Only the root node can produce the top level matcher","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/trees/tregex/tsurgeon/TsurgeonPattern.java","lineNumber":88,"sourceCode":"  @Override\n  public String toString() {\n    StringBuilder resultSB = new StringBuilder();\n    resultSB.append(label);\n    if (children.length > 0) {\n      resultSB.append('(');\n      for (int i = 0; i < children.length; i++) {\n        resultSB.append(children[i]);\n        if (i < children.length - 1) {\n          resultSB.append(\", \");\n        }\n      }\n      resultSB.append(')');\n    }\n    return resultSB.toString();\n  }\n\n  public TsurgeonMatcher matcher() {\n    throw new UnsupportedOperationException(\"Only the root node can produce the top level matcher\");\n  }\n\n  public abstract TsurgeonMatcher matcher(Map<String,Tree> newNodeNames, CoindexationGenerator coindexer);\n\n}\n","sourceCodeStart":70,"sourceCodeEnd":94,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/trees/tregex/tsurgeon/TsurgeonPattern.java#L70-L94","documentation":"The base TsurgeonPattern.matcher() is an unsupported default: only the root TsurgeonPattern (top of the parsed operation tree) is allowed to create a top-level TsurgeonMatcher via the no-argument matcher(). Calling matcher() on a child/inner pattern node throws this UnsupportedOperationException.","triggerScenarios":"Calling the no-arg matcher() directly on a non-root TsurgeonPattern (e.g. a node obtained from a parsed operation's children), instead of matcher(newNodeNames, coindexer) or the root pattern returned by parseOperation/Root().","commonSituations":"Programmatically walking the TsurgeonPattern tree and invoking matcher() on sub-nodes; custom tsurgeon node subclasses that fail to override the two-argument matcher; test code assuming matcher() works on any node.","solutions":["Call matcher() only on the root TsurgeonPattern returned by Tsurgeon.parseOperation or the parser's Root()","For inner nodes, use matcher(newNodeNames, coindexer) with a node-name map and coindexation generator","Ensure custom TsurgeonPattern subclasses implement the two-argument matcher()"],"exampleFix":"// before\nTsurgeonPattern child = ((TsurgeonRegexPattern) root).child;\nTsurgeonMatcher m = child.matcher(); // throws\n// after\nTsurgeonMatcher m = root.matcher(); // call on the root only","handlingStrategy":"type-guard","validationCode":"null","typeGuard":"boolean isRoot = pattern instanceof TsurgeonPatternRoot;\nif (!isRoot) throw new IllegalStateException(\"matcher() may only be called on the root TsurgeonPattern\");","tryCatchPattern":"try { TsurgeonMatcher m = pattern.matcher(); } catch (UnsupportedOperationException e) { throw new IllegalStateException(\"Use the root pattern's matcher(), not an inner node\", e); }","preventionTips":["Only invoke the no-arg matcher() on parseOperation/Root() results","Use matcher(newNodeNames, coindexer) for inner nodes","Track pattern provenance so sub-nodes are never treated as roots"],"tags":["tsurgeon","unsupported-operation","api-misuse"],"backgroundTag":"unsupported-operation","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"}