{"record":{"id":"4c486d3aebf3b554","repo":"gastownhall/beads","slug":"not-type-only-supports-operator","errorCode":null,"errorMessage":"NOT type only supports = operator","messagePattern":"NOT type only supports = operator","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/query/evaluator.go","lineNumber":599,"sourceCode":"\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:\n\t\treturn fmt.Errorf(\"NOT not supported for field %s in filter mode\", comp.Field)\n\t}\n}\n\n// parseTimeValue parses a time value from a comparison node.\n// Supports duration values (7d, 24h) which are interpreted as \"now - duration\".\nfunc (e *Evaluator) parseTimeValue(comp *ComparisonNode) (time.Time, error) {\n\tif comp.ValueType == TokenDuration {\n\t\t// Duration values like 7d mean \"7 days ago\" for < comparisons\n\t\t// and \"within the last 7 days\" for > comparisons\n\t\t// We parse as relative to now, going backwards\n\t\treturn e.parseDurationAgo(comp.Value)\n\t}","sourceCodeStart":581,"sourceCodeEnd":617,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/query/evaluator.go#L581-L617","documentation":"NOT type in filter mode appends to filter.ExcludeTypes and is implemented only for exact equality. Any other operator on NOT type raises this error. The parsed value becomes an IssueType added to the exclusion list.","triggerScenarios":"A query like `NOT type!=bug` or `NOT type=~feat` hitting applyNot's type case with comp.Op != OpEquals.","commonSituations":"Double negation (`NOT type!=bug`); assuming type-matching operators carry over to the NOT path; scripted query builders pairing != with NOT.","solutions":["Use `NOT type=bug` to exclude the bug type","Replace double negation: `NOT type!=bug` means `type=bug`","For regex/type-set matching use positive `type=~...` or `type IN (...)` without NOT","Chain multiple `NOT type=x` clauses to exclude several types"],"exampleFix":"// before\nbd list 'NOT type!=bug'\n// after\nbd list 'type=bug'  # or NOT type=bug to exclude bugs","handlingStrategy":"validation","validationCode":"if field == \"type\" && negated && op != \"=\" {\n    return fmt.Errorf(\"NOT type requires = (got %s)\", op)\n}","typeGuard":"func notTypeValid(op string) bool { return op == \"=\" }","tryCatchPattern":null,"preventionTips":["Write NOT type=<value> only","Replace NOT type!=x with type=x","Use type IN (...) or type=~... positively instead of negated variants"],"tags":["query","not-operator","type"],"backgroundTag":"query-operator-not-supported","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}