{"record":{"id":"a289c4cfef2e09a0","repo":"gastownhall/beads","slug":"status-only-supports-and-operators","errorCode":null,"errorMessage":"status only supports = and != operators","messagePattern":"status only supports = and != operators","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/query/evaluator.go","lineNumber":211,"sourceCode":"\tcase \"ephemeral\":\n\t\treturn e.applyBoolFilter(comp, filter, \"ephemeral\")\n\tcase \"template\":\n\t\treturn e.applyBoolFilter(comp, filter, \"template\")\n\tcase \"mol_type\":\n\t\treturn e.applyMolTypeFilter(comp, filter)\n\tcase \"has_metadata_key\":\n\t\treturn e.applyHasMetadataKeyFilter(comp, filter)\n\tdefault:\n\t\tif strings.HasPrefix(comp.Field, \"metadata.\") {\n\t\t\treturn e.applyMetadataFilter(comp, filter)\n\t\t}\n\t\treturn fmt.Errorf(\"unknown field: %s\", comp.Field)\n\t}\n}\n\nfunc (e *Evaluator) applyStatusFilter(comp *ComparisonNode, filter *types.IssueFilter) error {\n\tif comp.Op != OpEquals && comp.Op != OpNotEquals {\n\t\treturn fmt.Errorf(\"status only supports = and != operators\")\n\t}\n\tstatus := types.Status(strings.ToLower(comp.Value))\n\tif !status.IsValid() {\n\t\treturn fmt.Errorf(\"invalid status: %s\", comp.Value)\n\t}\n\tif comp.Op == OpEquals {\n\t\tfilter.Status = &status\n\t} else {\n\t\tfilter.ExcludeStatus = append(filter.ExcludeStatus, status)\n\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}","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/query/evaluator.go#L193-L229","documentation":"The status field in a beads query supports only the equality (=) and inequality (!=) operators. applyStatusFilter checks comp.Op before doing anything else and rejects ordering operators (>, <, >=, <=) and any other unsupported operator. Status is an enum, so range comparisons are meaningless and intentionally disallowed.","triggerScenarios":"Running a query like `status > open`, `status <= closed`, `status ~ in progress` — any ComparisonNode with Field=\"status\" and Op other than OpEquals/OpNotEquals.","commonSituations":"Users accustomed to SQL WHERE clauses trying `status < closed` to mean \"not yet closed\"; generated queries from generic query builders that emit ordering ops for every field; templates that interpolate an operator variable defaulting to `>=`.","solutions":["Rewrite the comparison using = (filter.Status) or != (filter.ExcludeStatus).","To express \"anything before closed\", enumerate statuses: `status = open OR status = in_progress OR ...`, or use != closed.","If programmatic, build the filter via types.IssueFilter directly (Status / ExcludeStatus fields) instead of going through the query parser."],"exampleFix":"// before\n\"status < closed\"\n// after\n\"status != closed\"","handlingStrategy":"validation","validationCode":"func validateStatusOp(op query.Op) error {\n    if op != query.OpEquals && op != query.OpNotEquals {\n        return fmt.Errorf(\"status supports only = and !=, got %v\", op)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := e.applyComparison(comp, filter); err != nil {\n    if strings.Contains(err.Error(), \"status only supports\") {\n        return rewriteToNotEquals(comp) // retry with = or !=\n    }\n    return err\n}","preventionTips":["Remember enums (status, type) never take ordering operators.","Express \"not yet closed\" as status != closed, not status < closed.","Test query templates with an operator-per-field matrix."],"tags":["query","operator","status","beads"],"backgroundTag":"unsupported-query-operator","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}