stanfordnlp/CoreNLP · error · IllegalStateException

Node cannot be both negated and optional.

Error message

Node cannot be both negated and optional.

What it means

TregexMatcher nodes carry neg and opt flags. A node cannot be simultaneously negated (!) and optional (?), since the semantics are contradictory (it both must not match and may match). TregexPattern.negate() throws IllegalStateException if the node is already optional.

Solutions

  1. Choose one: use either ! or ? for the node, not both
  2. Express the desired semantics differently, e.g. negation of a parent-level relation instead of an optional negated node
  3. In programmatic construction, check the opt flag before calling negate()

Example fix

// before
String pattern = "NP < !?CC";
// after
String pattern = "NP < !CC"; // or "NP < ?CC"
Defensive patterns

Strategy: validation

Validate before calling

// reject '?!' and '!?' combinations before compiling
if (pattern.contains("!?") || pattern.contains("?!")) throw new IllegalArgumentException("node cannot be both negated and optional: " + pattern);

Try / catch

try { TregexPattern.compile(pattern); } catch (IllegalStateException e) { /* negated+optional node; rewrite query */ }

Prevention

When it happens

Trigger: Calling negate() on a Description/TregexPattern node already marked optional, typically from parser actions in constructMultiRelation or ModChild when compiling patterns containing '?!' or '!?' node modifiers.

Common situations: Writing '!?' or '?!' combinations in a tregex query; programmatic pattern construction calling negate() and makeOptional() on the same node.

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

Appendix: source

Thrown at src/edu/stanford/nlp/trees/tregex/TregexPattern.java:370

 * @author Galen Andrew
 * @author Roger Levy (rog@csli.stanford.edu)
 * @author Anna Rafferty (filter mode)
 * @author John Bauer (extensively tested and bugfixed)
 */
public abstract class TregexPattern implements Serializable  {

  /** A logger for this class */
  private static final Redwood.RedwoodChannels log = Redwood.channels(TregexPattern.class);

  private boolean neg; // = false;
  private boolean opt; // = false;
  private String patternString;
  private Set<String> knownVariables;

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

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

  private void prettyPrint(PrintWriter pw, int indent) {
    for (int i = 0; i < indent; i++) {
      pw.print("   ");
    }
    if (neg) {
      pw.print('!');
    }
    if (opt) {

View on GitHub (pinned to 1b7edd19c4)