gastownhall/beads · error

OR not supported for this field combination

Error message

OR not supported for this field combination

What it means

During filter construction the query evaluator reaches an OrNode that could not be converted into the LabelsAny fast-path: collectOrLabels returned nil because the OR chain mixes non-label comparisons (e.g. status=open OR priority=1). The storage-backed filter has no representation for that OR shape, so buildFilter returns this error instead of silently producing wrong results.

Source

Thrown at internal/query/evaluator.go:150

func (e *Evaluator) buildFilter(node Node, filter *types.IssueFilter) error {
	switch n := node.(type) {
	case *ComparisonNode:
		return e.applyComparison(n, filter)
	case *AndNode:
		if err := e.buildFilter(n.Left, filter); err != nil {
			return err
		}
		return e.buildFilter(n.Right, filter)
	case *NotNode:
		return e.applyNot(n, filter)
	case *OrNode:
		// Only reached for LabelsAny optimization
		labels := e.collectOrLabels(n)
		if labels != nil {
			filter.LabelsAny = append(filter.LabelsAny, labels...)
			return nil
		}
		return fmt.Errorf("OR not supported for this field combination")
	default:
		return fmt.Errorf("unexpected node type: %T", node)
	}
}

// applyComparison applies a comparison to the filter.
func (e *Evaluator) applyComparison(comp *ComparisonNode, filter *types.IssueFilter) error {
	switch comp.Field {
	case "status":
		return e.applyStatusFilter(comp, filter)
	case "priority":
		return e.applyPriorityFilter(comp, filter)
	case "type":
		return e.applyTypeFilter(comp, filter)
	case "assignee":
		return e.applyAssigneeFilter(comp, filter)
	case "owner":
		return e.applyOwnerFilter(comp, filter)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Rewrite the filter so OR only chains label=X comparisons (those become LabelsAny)
  2. Split into multiple queries (one per OR branch) and union results client-side
  3. Use AND where semantics allow, since AND is fully supported by buildFilter
  4. If you control the query construction, only emit OrNodes after checking canUseLabelsAnyOptimization / collectOrLabels

Example fix

// before
// filter: "status = open OR priority = 1"
// after
// run two filtered queries and merge:
//   "status = open"
//   "priority = 1"
// or restrict ORs to: "label = a OR label = b"
Defensive patterns

Strategy: validation

Validate before calling

// Only emit OR nodes whose branches are all label equality comparisons
func orIsLabelOnly(n *query.OrNode, ev *query.Evaluator) bool {
    return ev.CanUseLabelsAnyOptimization(n)
}

Type guard

func buildSafeFilter(n query.Node, f *types.IssueFilter) error {
    if or, ok := n.(*query.OrNode); ok && !canUseLabelsAny(or) {
        return fmt.Errorf("unsupported OR; rewrite as label-only OR or split queries")
    }
    return nil
}

Try / catch

if err := evaluator.Evaluate(ast); err != nil {
    if strings.Contains(err.Error(), "OR not supported") {
        // fallback: split OR into separate queries and merge results
        return evaluateByParts(ast)
    }
    return err
}

Prevention

When it happens

Trigger: Evaluate/buildFilter receiving a parsed filter expression where an OR contains comparisons on fields other than label/labels with OpEquals — e.g. (status = open OR priority = 1) or (label = x OR title contains y).

Common situations: Users writing filter strings with OR across heterogeneous fields; programmatic ASTs combining OR with non-equality operators; after upgrading, previously lenient parsers now emit OrNodes the optimizer can't collapse.

Related errors


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