{"record":{"id":"42a2dc0ce47fdb55","repo":"gastownhall/beads","slug":"not-only-supports-simple-comparisons-in-filter-mod","errorCode":null,"errorMessage":"NOT only supports simple comparisons in filter mode","messagePattern":"NOT only supports simple comparisons in filter mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/query/evaluator.go","lineNumber":586,"sourceCode":"\t}\n\treturn func(i *types.Issue) bool {\n\t\tif len(i.Metadata) == 0 {\n\t\t\treturn false\n\t\t}\n\t\tvar data map[string]json.RawMessage\n\t\tif err := json.Unmarshal(i.Metadata, &data); err != nil {\n\t\t\treturn false\n\t\t}\n\t\t_, ok := data[key]\n\t\treturn ok\n\t}, nil\n}\n\n// applyNot applies a NOT expression to the filter.\nfunc (e *Evaluator) applyNot(not *NotNode, filter *types.IssueFilter) error {\n\tcomp, ok := not.Operand.(*ComparisonNode)\n\tif !ok {\n\t\treturn fmt.Errorf(\"NOT only supports simple comparisons in filter mode\")\n\t}\n\n\tswitch comp.Field {\n\tcase \"status\":\n\t\tif comp.Op != OpEquals {\n\t\t\treturn fmt.Errorf(\"NOT status only supports = operator\")\n\t\t}\n\t\tstatus := types.Status(strings.ToLower(comp.Value))\n\t\tfilter.ExcludeStatus = append(filter.ExcludeStatus, status)\n\t\treturn nil\n\tcase \"type\":\n\t\tif comp.Op != OpEquals {\n\t\t\treturn fmt.Errorf(\"NOT type only supports = operator\")\n\t\t}\n\t\tissueType := types.IssueType(strings.ToLower(comp.Value))\n\t\tfilter.ExcludeTypes = append(filter.ExcludeTypes, issueType)\n\t\treturn nil\n\tdefault:","sourceCodeStart":568,"sourceCodeEnd":604,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/query/evaluator.go#L568-L604","documentation":"In filter mode, NOT is translated into IssueFilter exclusion lists (ExcludeStatus, ExcludeTypes), which only exist for simple equality comparisons. applyNot type-asserts not.Operand to *ComparisonNode; if the operand is any other node (AND/OR group, nested NOT, etc.) the assertion fails and this error is returned. Nested or compound NOT expressions require predicate mode.","triggerScenarios":"Queries like `NOT (status=open OR priority=1)` or `NOT NOT status=open` where the NOT operand is not a single ComparisonNode, called from buildFilter or extractBaseFilters.","commonSituations":"Writing boolean-algebra style queries assuming full NOT generality; wrapping a group in NOT to 'invert' a complex clause; tools generating queries programmatically emitting NOT around compound expressions.","solutions":["Rewrite the query so NOT wraps a single field comparison, e.g. `NOT status=open`","Push the negation inward manually: `NOT (a OR b)` is generally not expressible; enumerate the exclusions instead, e.g. `NOT status=open NOT status=closed`","Avoid nested NOT; `NOT NOT x` is not supported in filter mode","If you need compound negation, run separate queries and combine results in a script"],"exampleFix":"// before\nbd list 'NOT (status=open OR priority=1)'\n// after\nbd list 'NOT status=open NOT priority=1'  # simple comparisons only in filter mode","handlingStrategy":"validation","validationCode":"// NOT must wrap a single field=value comparison in filter mode\nfunc notClauseValid(operandField, operandOp string) bool {\n    switch operandField {\n    case \"status\", \"type\":\n        return operandOp == \"=\"\n    default:\n        return false\n    }\n}","typeGuard":"func isSimpleComparison(n Node) (*ComparisonNode, bool) {\n    comp, ok := n.(*ComparisonNode)\n    return comp, ok\n}","tryCatchPattern":"result, err := eval.Evaluate(expr)\nif err != nil {\n    var nodeErr *NodeError\n    if strings.Contains(err.Error(), \"NOT only supports simple comparisons\") {\n        // rewrite query without compound NOT or fall back to client-side filtering\n    }\n    return result, err\n}","preventionTips":["Wrap NOT only around single field comparisons","Never nest NOT or wrap NOT around AND/OR groups in filter mode","Enumerate exclusions as multiple NOT status=x / NOT type=x clauses","For compound negation, combine query results in a script"],"tags":["query","not-operator","filter-mode"],"backgroundTag":"query-operator-not-supported","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}