stanfordnlp/CoreNLP · error · RuntimeException

Node cannot be both negated and optional.

Error message

Node cannot be both negated and optional.

What it means

SemgrexPattern.negate() throws this RuntimeException when the pattern node is already marked optional (opt == true). A node cannot simultaneously be negated and optional, since 'maybe absent' and 'must be absent' are contradictory match semantics, so the library treats the combination as an invalid state.

Solutions

  1. Remove either the optional ('?') or the negation ('!') modifier — decide whether the node should be optionally present or definitively absent.
  2. If the intent is 'fail if this node exists', keep negation and drop optionality (negation already implies the absence check).
  3. If the intent is 'match with or without this node', keep optionality and drop negation, or express it with an alternative ':' branch.
  4. Catch the RuntimeException at pattern-build time and report which pattern fragment combined the two modifiers.

Example fix

// before
SemgrexPattern.compile("{}=a ?!"); // optional + negated via ModRelation
// after
SemgrexPattern.compile("{}=a !"); // keep only negation
SemgrexPattern.compile("{}=a ?"); // or keep only optionality
Defensive patterns

Strategy: validation

Validate before calling

if (pattern.isNegated() && pattern.isOptional()) throw new IllegalArgumentException("Node is both negated and optional");

Try / catch

try { pattern.negate(); } catch (RuntimeException e) { throw new IllegalArgumentException("Conflicting ?/! modifiers on node", e); }

Prevention

When it happens

Trigger: Calling negate() on a SemgrexPattern whose 'opt' flag is already set — e.g. the parser's ModRelation path first marks a node optional via '?' and then applies negation ('!'), or programmatic construction calls makeOptional() before negate().

Common situations: Writing patterns like '[? !foo]' or equivalent modifier combinations parsed through ModRelation; programmatic pattern building where flags are applied in an order that allows both to be set; template-generated patterns where both modifiers are emitted unconditionally.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/edu/stanford/nlp/semgraph/semgrex/SemgrexPattern.java:265

  private String patternString; // conceptually final, but can't do because of parsing

  protected Env env; //always set with setEnv to make sure that it is also available to child patterns

  // package private constructor
  SemgrexPattern() {
  }

  // NodePattern will return its one child, CoordinationPattern will
  // return the list of children it conjuncts or disjuncts
  abstract List<SemgrexPattern> getChildren();

  abstract String localString();

  abstract void setChild(SemgrexPattern child);

  void negate() {
    if (opt) {
      throw new RuntimeException("Node cannot be both negated and optional.");
    }
    neg = true;
  }

  void makeOptional() {
    if (neg) {
      throw new RuntimeException("Node cannot be both negated and optional.");
    }
    opt = true;
  }

  boolean isNegated() {
    return neg;
  }

  boolean isOptional() {
    return opt;
  }

View on GitHub (pinned to 1b7edd19c4)