{"record":{"id":"2bdc94917ef8ff34","repo":"gastownhall/beads","slug":"priority-requires-predicate-filtering","errorCode":null,"errorMessage":"priority != requires predicate filtering","messagePattern":"priority != requires predicate filtering","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/query/evaluator.go","lineNumber":239,"sourceCode":"\t}\n\treturn nil\n}\n\nfunc (e *Evaluator) applyPriorityFilter(comp *ComparisonNode, filter *types.IssueFilter) error {\n\tpriority, err := strconv.Atoi(comp.Value)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid priority value: %s\", comp.Value)\n\t}\n\tif priority < 0 || priority > 4 {\n\t\treturn fmt.Errorf(\"priority must be between 0 and 4\")\n\t}\n\n\tswitch comp.Op {\n\tcase OpEquals:\n\t\tfilter.Priority = &priority\n\tcase OpNotEquals:\n\t\t// For != we need predicate filtering\n\t\treturn fmt.Errorf(\"priority != requires predicate filtering\")\n\tcase OpLess:\n\t\t// priority < X means PriorityMax = X-1\n\t\tmax := priority - 1\n\t\tif max < 0 {\n\t\t\treturn fmt.Errorf(\"priority < %d matches nothing\", priority)\n\t\t}\n\t\tfilter.PriorityMax = &max\n\tcase OpLessEq:\n\t\tfilter.PriorityMax = &priority\n\tcase OpGreater:\n\t\t// priority > X means PriorityMin = X+1\n\t\tmin := priority + 1\n\t\tif min > 4 {\n\t\t\treturn fmt.Errorf(\"priority > %d matches nothing\", priority)\n\t\t}\n\t\tfilter.PriorityMin = &min\n\tcase OpGreaterEq:\n\t\tfilter.PriorityMin = &priority","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/query/evaluator.go#L221-L257","documentation":"The IssueFilter struct backing queries has PriorityMin/PriorityMax range fields but no direct \"not equal\" representation for priority, so applyPriorityFilter explicitly refuses the != operator and tells the caller predicate filtering is required. This is a deliberate capability limit of the declarative filter, not a parsing bug.","triggerScenarios":"Queries like `priority != 2` — any ComparisonNode with Field=\"priority\" and Op=OpNotEquals.","commonSituations":"Users who just used `status != closed` (which IS supported) assuming all fields support !=; generated queries that emit != uniformly; older scripts written before this guard existed that silently mis-filtered.","solutions":["Use the Go API for predicate filtering: fetch with types.IssueFilter{Priority: ...} variants and post-filter in code: `if issue.Priority != want { skip }`.","Approximate with a range when the value is at the edge, e.g. `priority != 0` ≈ `priority >= 1`.","Otherwise enumerate the allowed values OR'd together (if the query language supports OR for priority in your build)."],"exampleFix":"// before\n\"priority != 2\"\n// after (client-side predicate)\nfilter, _ := query.Parse(\"priority >= 0\")\nissues = filterIssues(issues, func(i types.Issue) bool { return i.Priority != 2 })","handlingStrategy":"fallback","validationCode":"func supportsNotEquals(field string) bool { return field == \"status\" || field == \"type\" } // priority does not\nif op == query.OpNotEquals && field == \"priority\" { planClientSidePredicate() }","typeGuard":null,"tryCatchPattern":"if err := e.applyComparison(comp, filter); err != nil {\n    if strings.Contains(err.Error(), \"priority != requires predicate filtering\") {\n        return queryAllThenFilter(func(i types.Issue) bool { return i.Priority != want })\n    }\n    return err\n}","preventionTips":["Treat != as supported only for status and type.","Prefer range approximations at the edges (priority != 0 → priority >= 1).","When many rows are expected, fetch with a range filter and post-filter != in memory."],"tags":["query","priority","operator","beads"],"backgroundTag":"unsupported-query-operator","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}