gastownhall/beads · error

NOT not supported for field %s in filter mode

Error message

NOT not supported for field %s in filter mode

What it means

applyNot only supports NOT over the fields status and type in filter mode; any other field falls into the default case and raises this formatted error naming the field. Exclusion lists exist only for status and types, so NOT over priority, assignee, labels, metadata, etc. cannot be expressed as a filter.

Source

Thrown at internal/query/evaluator.go:605

	}

	switch comp.Field {
	case "status":
		if comp.Op != OpEquals {
			return fmt.Errorf("NOT status only supports = operator")
		}
		status := types.Status(strings.ToLower(comp.Value))
		filter.ExcludeStatus = append(filter.ExcludeStatus, status)
		return nil
	case "type":
		if comp.Op != OpEquals {
			return fmt.Errorf("NOT type only supports = operator")
		}
		issueType := types.IssueType(strings.ToLower(comp.Value))
		filter.ExcludeTypes = append(filter.ExcludeTypes, issueType)
		return nil
	default:
		return fmt.Errorf("NOT not supported for field %s in filter mode", comp.Field)
	}
}

// parseTimeValue parses a time value from a comparison node.
// Supports duration values (7d, 24h) which are interpreted as "now - duration".
func (e *Evaluator) parseTimeValue(comp *ComparisonNode) (time.Time, error) {
	if comp.ValueType == TokenDuration {
		// Duration values like 7d mean "7 days ago" for < comparisons
		// and "within the last 7 days" for > comparisons
		// We parse as relative to now, going backwards
		return e.parseDurationAgo(comp.Value)
	}
	// Otherwise use the standard time parser
	return timeparsing.ParseRelativeTime(comp.Value, e.now)
}

// parseDurationAgo parses a duration and returns now - duration.
func (e *Evaluator) parseDurationAgo(s string) (time.Time, error) {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Rewrite without NOT: use the field's positive operators, e.g. `priority!=1` if the field supports != directly
  2. For metadata/labels exclusions, filter results after the query in a script
  3. For status/type exclusions keep `NOT status=x` / `NOT type=x` forms which are supported
  4. Consider running two queries (with and without the value) and computing the difference client-side

Example fix

// before
bd list 'NOT priority=1'
// after
bd list 'priority!=1'  # use the field's own operators, not NOT, for non-status/type fields
Defensive patterns

Strategy: validation

Validate before calling

var notSupportedFields = map[string]bool{"status": true, "type": true}
if negated && !notSupportedFields[field] {
    return fmt.Errorf("field %s cannot be used with NOT; use its own operators", field)
}

Type guard

func notAllowedFor(field string) bool {
    return field != "status" && field != "type"
}

Prevention

When it happens

Trigger: Queries like `NOT priority=1`, `NOT assignee=alice`, or `NOT has_metadata_key=team` reaching applyNot's default branch from buildFilter or extractBaseFilters.

Common situations: Generalizing from 'NOT status works' to all fields; trying to exclude label/metadata values via NOT; older scripts written before metadata fields existed.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/7d4215e7aab2986c. Report an issue: GitHub.