{"record":{"id":"cdc3ba2c66a17818","repo":"stanfordnlp/CoreNLP","slug":"node-cannot-be-both-negated-and-optional-cdc3ba","errorCode":null,"errorMessage":"Node cannot be both negated and optional.","messagePattern":"Node cannot be both negated and optional\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/trees/tregex/TregexPattern.java","lineNumber":370,"sourceCode":" * @author Galen Andrew\n * @author Roger Levy (rog@csli.stanford.edu)\n * @author Anna Rafferty (filter mode)\n * @author John Bauer (extensively tested and bugfixed)\n */\npublic abstract class TregexPattern implements Serializable  {\n\n  /** A logger for this class */\n  private static final Redwood.RedwoodChannels log = Redwood.channels(TregexPattern.class);\n\n  private boolean neg; // = false;\n  private boolean opt; // = false;\n  private String patternString;\n  private Set<String> knownVariables;\n\n  void negate() {\n    neg = true;\n    if (opt) {\n      throw new IllegalStateException(\"Node cannot be both negated and optional.\");\n    }\n  }\n\n  void makeOptional() {\n    opt = true;\n    if (neg) {\n      throw new IllegalStateException(\"Node cannot be both negated and optional.\");\n    }\n  }\n\n  private void prettyPrint(PrintWriter pw, int indent) {\n    for (int i = 0; i < indent; i++) {\n      pw.print(\"   \");\n    }\n    if (neg) {\n      pw.print('!');\n    }\n    if (opt) {","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/trees/tregex/TregexPattern.java#L352-L388","documentation":"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.","triggerScenarios":"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.","commonSituations":"Writing '!?' or '?!' combinations in a tregex query; programmatic pattern construction calling negate() and makeOptional() on the same node.","solutions":["Choose one: use either ! or ? for the node, not both","Express the desired semantics differently, e.g. negation of a parent-level relation instead of an optional negated node","In programmatic construction, check the opt flag before calling negate()"],"exampleFix":"// before\nString pattern = \"NP < !?CC\";\n// after\nString pattern = \"NP < !CC\"; // or \"NP < ?CC\"","handlingStrategy":"validation","validationCode":"// reject '?!' and '!?' combinations before compiling\nif (pattern.contains(\"!?\") || pattern.contains(\"?!\")) throw new IllegalArgumentException(\"node cannot be both negated and optional: \" + pattern);","typeGuard":null,"tryCatchPattern":"try { TregexPattern.compile(pattern); } catch (IllegalStateException e) { /* negated+optional node; rewrite query */ }","preventionTips":["Never combine ! and ? on the same node","In programmatic construction, guard negate()/makeOptional() with flag checks","Rework the query semantics rather than mixing the two modifiers"],"tags":["tregex","invalid-state","pattern-parsing"],"backgroundTag":"invalid-state-transition","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}