{"record":{"id":"dcdedccc5538fe6e","repo":"stanfordnlp/CoreNLP","slug":"tsurgeon-processpatternsontree-failed-to-match-lab","errorCode":null,"errorMessage":"Tsurgeon.processPatternsOnTree failed to match label for pattern: \" + op.first() + \", \" + op.second()","messagePattern":"Tsurgeon\\.processPatternsOnTree failed to match label for pattern: \" \\+ op\\.first\\(\\) \\+ \", \" \\+ op\\.second\\(\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/trees/tregex/tsurgeon/Tsurgeon.java","lineNumber":627,"sourceCode":"        }\n        TregexMatcher m = op.first().matcher(t);\n        TsurgeonMatcher tsm = op.second().matcher();\n        while (m.find()) {\n          matchedOnTree = true;\n          t = tsm.evaluate(t,m);\n          if (t == null) {\n            if (DEBUG) {\n              log.info(\"  Matched, but t == null!\");\n            }\n            return null;\n          }\n          if (DEBUG) {\n            log.info(\"  Matched!  Update: \" + t);\n          }\n          m = op.first().matcher(t);\n        }\n      } catch (NullPointerException npe) {\n        throw new RuntimeException(\"Tsurgeon.processPatternsOnTree failed to match label for pattern: \" + op.first() + \", \" + op.second(), npe);\n      }\n    }\n    return t;\n  }\n\n\n\n  /**\n   * Parses an operation string into a {@link TsurgeonPattern}.  Throws an {@link TsurgeonParseException} if\n   * the operation string is ill-formed.\n   * <p>\n   * Example of use:\n   * <p>\n   * <code>\n   * TsurgeonPattern p = Tsurgeon.parseOperation(\"prune ed\");\n   * </code>\n   * @param operationString The operation to perform, as a text string\n   * @return the operation pattern.","sourceCodeStart":609,"sourceCodeEnd":645,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/trees/tregex/tsurgeon/Tsurgeon.java#L609-L645","documentation":"In Tsurgeon.processPatternsOnTree, after a tregex match succeeds, the code re-runs matcher() on the updated tree; if that throws NullPointerException (typically because the tree or match structure is null after a previous operation rewrote it), it is wrapped in this RuntimeException naming the failing pattern and operation pair.","triggerScenarios":"Running a sequence of (tregex, tsurgeon) pairs where an earlier operation deletes or restructures nodes so that a later pattern's matcher on the modified tree produces a null label/match, hitting the NPE catch in processPatternsOnTree.","commonSituations":"Chained tsurgeon scripts where op N's output violates op N+1's tregex assumptions; delete/prune followed by operations that assume the node still exists; coindexation nodes removed by earlier edits.","solutions":["Make later patterns tolerant: re-anchor them so they only match structures that exist after earlier operations","Split the processing into stages, calling processPatternsOnTree separately per operation set","Validate the tree between operations (log/inspect it) to find which operation produces the null match","Catch RuntimeException and skip/restore the tree for the failing sentence"],"exampleFix":"// before\nList<Pair<TregexPattern,TsurgeonPattern>> ops = ...; // ops assume deleted nodes still exist\nTsurgeon.processPatternsOnTree(ops, tree);\n// after\n// run destructive ops first, then dependent ops on the updated tree\nTsurgeon.processPatternsOnTree(Collections.singletonList(destructiveOp), tree);\nTsurgeon.processPatternsOnTree(Collections.singletonList(dependentOp), tree);","handlingStrategy":"try-catch","validationCode":"// ensure the tree matches before applying dependent operations\nif (tregex.matcher(tree).find()) {\n  Tsurgeon.processPatternsOnTree(Collections.singletonList(op), tree);\n}","typeGuard":"if (tree == null || tree.label() == null) { skip(); return; }","tryCatchPattern":"try {\n  tree = Tsurgeon.processPatternsOnTree(ops, tree);\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"failed to match label\")) {\n    log.warn(\"Skipping sentence: pattern no longer matches after earlier op\", e);\n  } else throw e;\n}","preventionTips":["Design each tregex pattern to match structures surviving earlier operations","Split dependent operations into separate processPatternsOnTree stages","Log the tree after each operation when debugging chains","Avoid operations that delete nodes referenced by later patterns"],"tags":["tsurgeon","tregex","null-pointer","runtime-exception"],"backgroundTag":"null-argument","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"}