gastownhall/beads · error

spec with wildcard only supports = and != operators

Error message

spec with wildcard only supports = and != operators

What it means

The spec field supports wildcard (prefix*) matching only with = and !=. buildSpecPredicate returns this error when a wildcard spec value is combined with any other operator, mirroring the id-field rule: prefix matching has no ordering semantics.

Source

Thrown at internal/query/evaluator.go:1011

	case OpNotEquals:
		return func(i *types.Issue) bool { return i.ID != value }, nil
	default:
		return nil, fmt.Errorf("id does not support %s operator", comp.Op.String())
	}
}

func (e *Evaluator) buildSpecPredicate(comp *ComparisonNode) (func(*types.Issue) bool, error) {
	value := comp.Value
	hasWildcard := strings.HasSuffix(value, "*")
	if hasWildcard {
		prefix := strings.TrimSuffix(value, "*")
		switch comp.Op {
		case OpEquals:
			return func(i *types.Issue) bool { return strings.HasPrefix(i.SpecID, prefix) }, nil
		case OpNotEquals:
			return func(i *types.Issue) bool { return !strings.HasPrefix(i.SpecID, prefix) }, nil
		default:
			return nil, fmt.Errorf("spec with wildcard only supports = and != operators")
		}
	}
	switch comp.Op {
	case OpEquals:
		return func(i *types.Issue) bool { return i.SpecID == value }, nil
	case OpNotEquals:
		return func(i *types.Issue) bool { return i.SpecID != value }, nil
	default:
		return nil, fmt.Errorf("spec does not support %s operator", comp.Op.String())
	}
}

func (e *Evaluator) buildBoolPredicate(comp *ComparisonNode, getter func(*types.Issue) bool) (func(*types.Issue) bool, error) {
	val := strings.ToLower(comp.Value)
	var boolVal bool
	switch val {
	case "true", "yes", "1":
		boolVal = true

View on GitHub (pinned to 71377f2769)

Solutions

  1. Switch to spec = prefix* for prefix match or spec != prefix* for exclusion.
  2. Drop the wildcard for an exact spec match: spec = bd-123.
  3. Combine multiple prefix matches with OR clauses.
  4. Constrain any programmatic query emitter to equality operators for spec.

Example fix

// before
bd list --query "spec >= auth*"
// after
bd list --query "spec = auth*"
Defensive patterns

Strategy: validation

Validate before calling

func checkSpecQuery(op Operator, value string) error {
	if strings.HasSuffix(value, "*") && op != OpEquals && op != OpNotEquals {
		return fmt.Errorf("spec wildcard requires = or !=")
	}
	return nil
}

Type guard

func isWildcardSpecQuery(op Operator, value string) bool {
	return strings.HasSuffix(value, "*") && (op == OpEquals || op == OpNotEquals)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "spec with wildcard only supports") {
	return fmt.Errorf("use spec = prefix* or spec != prefix*: %w", err)
}

Prevention

When it happens

Trigger: A query like `spec > auth*` or `spec <= obs*` — wildcard-terminated spec id with a non-equality operator, reaching buildComparisonPredicate.

Common situations: Reusing range-query syntax across fields; mistaking spec for a sortable field; generated queries from dashboards or scripts that append operators uniformly.

Related errors


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