stanfordnlp/CoreNLP · error · SemgrexParseException

Semgrex pattern asked for uniq of node

Error message

Semgrex pattern asked for uniq of node 

What it means

The '::' unique operator in semgrex requires the listed keys to be node names already declared elsewhere in the pattern. If a key after '::' was never defined as a node variable, the parser throws SemgrexParseException saying the pattern asked for uniq of a node that does not exist.

Solutions

  1. Define the node with '=key' somewhere in the pattern before/alongside using '::key'
  2. Fix the spelling so the '::' key matches an existing node variable
  3. Remove the non-existent key from the '::' list

Example fix

// before
SemgrexPattern p = SemgrexPattern.compile("::x {} >nsubj =y");
// after
SemgrexPattern p = SemgrexPattern.compile("::y {} >nsubj =y");
Defensive patterns

Strategy: validation

Validate before calling

Set<String> declared = new HashSet<>();
Matcher m = Pattern.compile("=(\\w+)").matcher(pattern.substring(pattern.indexOf("::") + 2));
// collect node vars outside '::' and check each '::key' is in the declared set before compiling

Try / catch

try {
  p = SemgrexPattern.compile(pattern);
} catch (SemgrexParseException e) {
  if (e.getMessage().startsWith("Semgrex pattern asked for uniq")) { /* fix or drop the bad '::key' */ }
  throw e;
}

Prevention

When it happens

Trigger: Compiling a pattern like '::x {}' or '::a,b {...}' where 'x' (or 'a'/'b') never appears as '=x' on any node in the pattern.

Common situations: Typos in node variable names; referring to edge names or attribute names in '::'; reordering a pattern so the '::' clause references variables defined later than expected.

Related errors


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

Appendix: source

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

    )
    {
      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);
      }
    )?
  )
  (
    "\n"
  )
  {
    return node;
  }

}

View on GitHub (pinned to 1b7edd19c4)