{"record":{"id":"51877394aa4199f7","repo":"gastownhall/beads","slug":"notes-only-supports-operator","errorCode":null,"errorMessage":"notes only supports = operator","messagePattern":"notes only supports = operator","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/query/evaluator.go","lineNumber":326,"sourceCode":"\tfilter.TitleContains = comp.Value\n\treturn nil\n}\n\nfunc (e *Evaluator) applyDescriptionFilter(comp *ComparisonNode, filter *types.IssueFilter) error {\n\tif comp.Op != OpEquals {\n\t\treturn fmt.Errorf(\"description only supports = operator (use desc contains pattern)\")\n\t}\n\tif comp.Value == \"\" || strings.ToLower(comp.Value) == \"none\" || strings.ToLower(comp.Value) == \"null\" {\n\t\tfilter.EmptyDescription = true\n\t} else {\n\t\tfilter.DescriptionContains = comp.Value\n\t}\n\treturn nil\n}\n\nfunc (e *Evaluator) applyNotesFilter(comp *ComparisonNode, filter *types.IssueFilter) error {\n\tif comp.Op != OpEquals {\n\t\treturn fmt.Errorf(\"notes only supports = operator\")\n\t}\n\tfilter.NotesContains = comp.Value\n\treturn nil\n}\n\nfunc (e *Evaluator) applyCreatedFilter(comp *ComparisonNode, filter *types.IssueFilter) error {\n\tt, err := e.parseTimeValue(comp)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid created time: %w\", err)\n\t}\n\tswitch comp.Op {\n\tcase OpEquals:\n\t\t// For equals, set both before and after to bracket the day\n\t\tdayStart := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())\n\t\tdayEnd := dayStart.Add(24 * time.Hour)\n\t\tfilter.CreatedAfter = &dayStart\n\t\tfilter.CreatedBefore = &dayEnd\n\tcase OpGreater:","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/query/evaluator.go#L308-L344","documentation":"applyNotesFilter only permits the = operator on the notes field, implemented as a substring match via filter.NotesContains. Any other operator is rejected. Unlike assignee/label/description, notes has no special 'none' handling — the raw value (even empty) becomes NotesContains.","triggerScenarios":"Queries like `notes != x`, `notes contains foo`, or `notes ~ y` reach applyNotesFilter with comp.Op != OpEquals and return this error.","commonSituations":"Users searching agent/audit notes with contains syntax; attempts to exclude issues mentioning a string via !=; queries modeled on the predicate-mode notes API.","solutions":["Use `notes = <substring>` in filter mode (substring match)","Use predicate mode where notes contains / other operators are supported via buildNotesPredicate","Exclude notes matches by post-filtering results in application code"],"exampleFix":"// before\nbd list 'notes contains escalated'\n// after\nbd list 'notes = escalated'","handlingStrategy":"validation","validationCode":"// Validate notes comparisons before evaluation\nif comp.Field == \"notes\" && comp.Op != OpEquals {\n\treturn fmt.Errorf(\"use 'notes = <substring>' in filter mode\")\n}","typeGuard":"func notesOpSupported(op Op) bool { return op == OpEquals }","tryCatchPattern":"if err := eval.applyComparison(comp, filter); err != nil {\n\tif strings.Contains(err.Error(), \"notes only supports = operator\") {\n\t\t// rewrite to notes = <substring> or use predicate mode\n\t}\n}","preventionTips":["Always use `notes = <substring>` (implemented as contains)","Use predicate mode for non-equality notes operators","Post-filter note exclusions in application code instead of using !="],"tags":["query","filter","notes","unsupported-operator"],"backgroundTag":"unsupported-query-operator","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}