gastownhall/beads · error

status only supports = and != operators

Error message

status only supports = and != operators

What it means

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.

Source

Thrown at internal/query/evaluator.go:211

	case "ephemeral":
		return e.applyBoolFilter(comp, filter, "ephemeral")
	case "template":
		return e.applyBoolFilter(comp, filter, "template")
	case "mol_type":
		return e.applyMolTypeFilter(comp, filter)
	case "has_metadata_key":
		return e.applyHasMetadataKeyFilter(comp, filter)
	default:
		if strings.HasPrefix(comp.Field, "metadata.") {
			return e.applyMetadataFilter(comp, filter)
		}
		return fmt.Errorf("unknown field: %s", comp.Field)
	}
}

func (e *Evaluator) applyStatusFilter(comp *ComparisonNode, filter *types.IssueFilter) error {
	if comp.Op != OpEquals && comp.Op != OpNotEquals {
		return fmt.Errorf("status only supports = and != operators")
	}
	status := types.Status(strings.ToLower(comp.Value))
	if !status.IsValid() {
		return fmt.Errorf("invalid status: %s", comp.Value)
	}
	if comp.Op == OpEquals {
		filter.Status = &status
	} else {
		filter.ExcludeStatus = append(filter.ExcludeStatus, status)
	}
	return nil
}

func (e *Evaluator) applyPriorityFilter(comp *ComparisonNode, filter *types.IssueFilter) error {
	priority, err := strconv.Atoi(comp.Value)
	if err != nil {
		return fmt.Errorf("invalid priority value: %s", comp.Value)
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Rewrite the comparison using = (filter.Status) or != (filter.ExcludeStatus).
  2. To express "anything before closed", enumerate statuses: `status = open OR status = in_progress OR ...`, or use != closed.
  3. If programmatic, build the filter via types.IssueFilter directly (Status / ExcludeStatus fields) instead of going through the query parser.

Example fix

// before
"status < closed"
// after
"status != closed"
Defensive patterns

Strategy: validation

Validate before calling

func validateStatusOp(op query.Op) error {
    if op != query.OpEquals && op != query.OpNotEquals {
        return fmt.Errorf("status supports only = and !=, got %v", op)
    }
    return nil
}

Try / catch

if err := e.applyComparison(comp, filter); err != nil {
    if strings.Contains(err.Error(), "status only supports") {
        return rewriteToNotEquals(comp) // retry with = or !=
    }
    return err
}

Prevention

When it happens

Trigger: Running a query like `status > open`, `status <= closed`, `status ~ in progress` — any ComparisonNode with Field="status" and Op other than OpEquals/OpNotEquals.

Common situations: 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 `>=`.

Related errors


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