gastownhall/beads · error

id with wildcard only supports = and != operators

Error message

id with wildcard only supports = and != operators

What it means

The id field supports wildcard matching (prefix*) only with the = and != operators. buildIDPredicate returns this error when a wildcard id value is combined with any other comparison operator (>, <, >=, <=, etc.), because ordering a string prefix match is undefined.

Source

Thrown at internal/query/evaluator.go:987

	case OpGreaterEq:
		return actual.After(target) || actual.Equal(target)
	default:
		return false
	}
}

func (e *Evaluator) buildIDPredicate(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.ID, prefix) }, nil
		case OpNotEquals:
			return func(i *types.Issue) bool { return !strings.HasPrefix(i.ID, prefix) }, nil
		default:
			return nil, fmt.Errorf("id with wildcard only supports = and != operators")
		}
	}
	switch comp.Op {
	case OpEquals:
		return func(i *types.Issue) bool { return i.ID == value }, nil
	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 {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Remove the wildcard and use exact match with = or != (e.g. id = bd-123).
  2. Keep the wildcard but switch the operator to = (prefix match) or != (prefix exclusion).
  3. For multiple prefixes, OR separate wildcard equality clauses: id = bd-1* OR id = bd-2*.
  4. Sanitize query builders so wildcard values are only emitted with equality operators.

Example fix

// before
bd list --query "id >= bd-1*"
// after
bd list --query "id = bd-1*"   // prefix match on all bd-1x ids
Defensive patterns

Strategy: validation

Validate before calling

func checkIDQuery(field, op, value string) error {
	if strings.HasSuffix(value, "*") && op != "=" && op != "!=" {
		return fmt.Errorf("wildcard %s requires = or !=", field)
	}
	return nil
}

Type guard

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

Try / catch

pred, err := e.Evaluate(q)
if err != nil {
	if strings.Contains(err.Error(), "only supports = and != operators") {
		// rewrite query with = and retry
	}
	return err
}

Prevention

When it happens

Trigger: A query like `id > bd-1*` or `id <= abc*` — any wildcard-terminated id value used with an operator other than = or !=.

Common situations: Copy-pasting a range query pattern from time/numeric fields and applying it to id; trying to express 'starts with' via >=; script generators emitting uniform operator syntax across all fields.

Related errors


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