gastownhall/beads · error

NOT status only supports = operator

Error message

NOT status only supports = operator

What it means

NOT status in filter mode maps to appending to filter.ExcludeStatus, which is only defined for exact status equality. Any other operator (!=, =~, IN) on NOT status is rejected with this error. Note the asymmetry: plain status supports more operators, but the NOT path only implements =.

Source

Thrown at internal/query/evaluator.go:592

		if err := json.Unmarshal(i.Metadata, &data); err != nil {
			return false
		}
		_, ok := data[key]
		return ok
	}, nil
}

// applyNot applies a NOT expression to the filter.
func (e *Evaluator) applyNot(not *NotNode, filter *types.IssueFilter) error {
	comp, ok := not.Operand.(*ComparisonNode)
	if !ok {
		return fmt.Errorf("NOT only supports simple comparisons in filter mode")
	}

	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".

View on GitHub (pinned to 71377f2769)

Solutions

  1. Use `NOT status=open` (excludes that status) — the only supported NOT status form
  2. For 'NOT status!=open' (double negation), simply write `status=open`
  3. For regex or IN semantics on status, use the positive form `status=~...` / `status IN (...)` without NOT
  4. Combine multiple `NOT status=x` clauses to exclude several statuses

Example fix

// before
bd list 'NOT status!=open'
// after
bd list 'status=open'  # or NOT status=open for exclusion
Defensive patterns

Strategy: validation

Validate before calling

if field == "status" && negated && op != "=" {
    return fmt.Errorf("NOT status requires = (got %s)", op)
}

Type guard

func notStatusValid(op string) bool { return op == "=" }

Prevention

When it happens

Trigger: A query like `NOT status!=open` or `NOT status=~in_progress` reaching applyNot's status case with comp.Op != OpEquals.

Common situations: Double negation attempts ('NOT status!=open' meaning status=open); users expecting regex exclusion support; generated queries combining NOT with inequality operators.

Related errors


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