stanfordnlp/CoreNLP · error · RuntimeException

Tsurgeon.processPatternsOnTree failed to match label for…

Error message

Tsurgeon.processPatternsOnTree failed to match label for pattern: " + op.first() + ", " + op.second()

What it means

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.

Solutions

  1. Make later patterns tolerant: re-anchor them so they only match structures that exist after earlier operations
  2. Split the processing into stages, calling processPatternsOnTree separately per operation set
  3. Validate the tree between operations (log/inspect it) to find which operation produces the null match
  4. Catch RuntimeException and skip/restore the tree for the failing sentence

Example fix

// before
List<Pair<TregexPattern,TsurgeonPattern>> ops = ...; // ops assume deleted nodes still exist
Tsurgeon.processPatternsOnTree(ops, tree);
// after
// run destructive ops first, then dependent ops on the updated tree
Tsurgeon.processPatternsOnTree(Collections.singletonList(destructiveOp), tree);
Tsurgeon.processPatternsOnTree(Collections.singletonList(dependentOp), tree);
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the tree matches before applying dependent operations
if (tregex.matcher(tree).find()) {
  Tsurgeon.processPatternsOnTree(Collections.singletonList(op), tree);
}

Type guard

if (tree == null || tree.label() == null) { skip(); return; }

Try / catch

try {
  tree = Tsurgeon.processPatternsOnTree(ops, tree);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().contains("failed to match label")) {
    log.warn("Skipping sentence: pattern no longer matches after earlier op", e);
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/dcdedccc5538fe6e. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/trees/tregex/tsurgeon/Tsurgeon.java:627

        }
        TregexMatcher m = op.first().matcher(t);
        TsurgeonMatcher tsm = op.second().matcher();
        while (m.find()) {
          matchedOnTree = true;
          t = tsm.evaluate(t,m);
          if (t == null) {
            if (DEBUG) {
              log.info("  Matched, but t == null!");
            }
            return null;
          }
          if (DEBUG) {
            log.info("  Matched!  Update: " + t);
          }
          m = op.first().matcher(t);
        }
      } catch (NullPointerException npe) {
        throw new RuntimeException("Tsurgeon.processPatternsOnTree failed to match label for pattern: " + op.first() + ", " + op.second(), npe);
      }
    }
    return t;
  }



  /**
   * Parses an operation string into a {@link TsurgeonPattern}.  Throws an {@link TsurgeonParseException} if
   * the operation string is ill-formed.
   * <p>
   * Example of use:
   * <p>
   * <code>
   * TsurgeonPattern p = Tsurgeon.parseOperation("prune ed");
   * </code>
   * @param operationString The operation to perform, as a text string
   * @return the operation pattern.

View on GitHub (pinned to 1b7edd19c4)