stanfordnlp/CoreNLP · error · SemgrexParseException

Use of node conjugation (expressions such as '< [foo bar]'…

Error message

Use of node conjugation (expressions such as '< [foo bar]' or '< [foo & bar]') is now illegal.  The issue is that expressions such as '[foo bar] < zzz' may intuitively mean that foo < zzz, bar < zzz, zzz the same for both cases, but that is not the way the parser interpreted this expression.  Changing the functionality might break existing expressions, and anyway this can be rewritten in various ways such as 'zzz > foo > bar' or 'foo < zzz=a : bar < zzz=a'.  Offending expression: 

What it means

SemgrexParser rejects node conjugation — bracketed multi-expression patterns attached via a relation such as '< [foo bar]' or '< [foo & bar]'. The parser's interpretation differs from intuition (it does not mean each element independently relates), so changing it would break existing patterns; instead the construct is made illegal and a SemgrexParseException naming the offending token is thrown.

Solutions

  1. Rewrite as sequential relations, e.g. 'zzz > foo > bar'
  2. Use named edges with separate matches: 'foo < zzz=a : bar < zzz=a'
  3. Drop the inner '&' and restate each relation explicitly in separate conjuncts

Example fix

// before
SemgrexPattern p = SemgrexPattern.compile("{} < [foo bar]");
// after
SemgrexPattern p = SemgrexPattern.compile("{} > foo > bar");
Defensive patterns

Strategy: validation

Validate before calling

java.util.regex.Pattern nodeConj = java.util.regex.Pattern.compile("\\\\?\s*<\s*\\[[^\\]]*(&|\\s)[^\\]]*\\]");
if (nodeConj.matcher(pattern).find()) throw new IllegalArgumentException("node conjugation is illegal in semgrex: " + pattern);

Try / catch

try {
  p = SemgrexPattern.compile(pattern);
} catch (SemgrexParseException e) {
  if (e.getMessage().startsWith("Use of node conjugation")) { /* rewrite pattern to sequential relations */ }
  throw e;
}

Prevention

When it happens

Trigger: Compiling a semgrex pattern using node conjugation syntax, e.g. '{pos:VBZ} < [nsubj dobj]' or any bracketed expression combined with '&' as node conjunction.

Common situations: Migrating very old semgrex patterns; translating tregex habits into semgrex; tutorials predating the syntax change.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/semgraph/semgrex/SemgrexParser.jj:109

    // start from 1 since we haven't parsed anything yet
    startToken = getToken(1);
  }
  (
    (
      (reverse = <ALIGNRELN> node = SubNode(GraphRelation.ALIGNED_ROOT))
      |
      ( node = SubNode(GraphRelation.ROOT) { children.add(node); }
        ( ":" node = SubNode(GraphRelation.ITERATOR) { children.add(node); } )*
      )
    )
    {
      if (children.size() > 1)
        node = new CoordinationPattern(true, children, true, true);
      if (deprecatedAmp) {
        throw new SemgrexParseException("Use of & in semgrex patterns is now illegal.  It is equivalent to the same expression without the &.  Offending expression: " + startToken);
      }
      if (deprecatedNodeConj) {
        throw new SemgrexParseException("Use of node conjugation (expressions such as '< [foo bar]' or '< [foo & bar]') is now illegal.  The issue is that expressions such as '[foo bar] < zzz' may intuitively mean that foo < zzz, bar < zzz, zzz the same for both cases, but that is not the way the parser interpreted this expression.  Changing the functionality might break existing expressions, and anyway this can be rewritten in various ways such as 'zzz > foo > bar' or 'foo < zzz=a : bar < zzz=a'.  Offending expression: " + startToken);
      }
    }
  )
  (
    (
      "::" <UNIQ> { uniqKeys = new ArrayList<>(); }  (nextIdentifier = identifier() { uniqKeys.add(nextIdentifier.image); })*
      {
        for (String key : uniqKeys) {
          if (!knownVariables.contains(key)) {
            throw new SemgrexParseException("Semgrex pattern asked for uniq of node " + key + " which does not exist in the pattern");
          }
        }
        // TODO: can error check that the keys are unique between node and edge names
        // that might require keeping edge names in a known set
        // TODO: edge names might need some upgrades anyway - shouldn't name them under negation, for example
        node = new UniqPattern(node, uniqKeys);
      }
    )?

View on GitHub (pinned to 1b7edd19c4)