stanfordnlp/CoreNLP · error · SemgrexParseException

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

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 throws this SemgrexParseException during Root() when a pattern uses the deprecated node-conjugation syntax, i.e. applying a relation to a bracketed coordination like '< [foo bar]' or '< [foo & bar]'. The parser's interpretation of such expressions does not match developers' intuition (that each element is compared to the outside node), so the construct was removed rather than redefined, since changing semantics would silently break existing patterns.

Solutions

  1. Rewrite the coordination as chained relations that compare each node to the shared target, e.g. 'zzz > foo > bar' or 'foo < zzz=a : bar < zzz=a'.
  2. Remove the '&' inside brackets — it was already a no-op equivalent to a space, but the whole construct is now illegal.
  3. Split the pattern into multiple compiled patterns joined with ':' branches so each relation applies to a single named node.
  4. If the pattern comes from a config or rule file, update the rule text, not the code; the exception names the offending expression in startToken.

Example fix

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

Strategy: validation

Validate before calling

private static final Pattern NODE_CONJ = Pattern.compile("[<>]\\s*\\[[^]]*\\]");
if (NODE_CONJ.matcher(semgrex).find()) throw new IllegalArgumentException("Node conjugation is illegal: " + semgrex);

Try / catch

try { SemgrexPattern.compile(semgrex); } catch (SemgrexParseException e) { log.warn("Deprecated node conjugation in: {}", semgrex); }

Prevention

When it happens

Trigger: Calling SemgrexPattern.compile(...) with a pattern where a relation symbol ('<', '>', etc.) targets a bracketed group of node expressions, e.g. '< [foo bar]' or the deprecated '< [foo & bar]' form; the parser sets deprecatedNodeConj and throws before returning a pattern.

Common situations: Upgrading old Stanford Semgrex patterns written for legacy semgrex syntax; porting extraction rules or Ssurgeon scripts from older CoreNLP versions where node conjunction was legal; copy-pasting regex-like patterns that assume conjunctive comparison semantics.

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/eeb914a6d1aa076c. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/semgraph/semgrex/SemgrexParser.java:101

        }
        jj_consume_token(10);
        node = SubNode(GraphRelation.ITERATOR);
children.add(node);
      }
      break;
      }
    default:
      jj_la1[1] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
if (children.size() > 1)
        node = new CoordinationPattern(true, children, true, true);
      if (deprecatedAmp) {
        {if (true) 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) {
        {if (true) 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);}
      }
    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
    case 11:{
      jj_consume_token(11);
      jj_consume_token(UNIQ);
uniqKeys = new ArrayList<>();
      label_2:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case UNIQ:
        case IDENTIFIER:{
          ;
          break;
          }
        default:
          jj_la1[2] = jj_gen;
          break label_2;
        }

View on GitHub (pinned to 1b7edd19c4)