jaegertracing/jaeger · error · ErrFilterUnsupported

%w: it does not support the operator %q

Error message

%w: it does not support the operator %q

What it means

FilterCapabilities.EnsureSupported recursively validates a filter expression against what a Reader declared it can evaluate. When the Reader's capability set does not include the operator used by a Call node in the filter, it returns ErrFilterUnsupported wrapped with the operator name.

Source

Thrown at internal/storage/v2/api/tracestore/admission.go:74

// caller's to settle first.
func (q TraceQueryParams) ForCapabilities(caps SearchCapabilities) (TraceQueryParams, error) {
	if q.Filter == nil {
		return q, nil
	}
	if caps.Filter.IsEmpty() {
		return q.ToLegacyShape()
	}
	return q, caps.Filter.EnsureSupported(q.Filter)
}

// EnsureSupported walks the filter and refuses the first predicate the Reader did not declare it
// can evaluate.
func (c FilterCapabilities) EnsureSupported(filter *expression.Call) error {
	if filter == nil {
		return nil
	}
	if !c.SupportsOperator(filter.Op) {
		return fmt.Errorf("%w: it does not support the operator %q", ErrFilterUnsupported, filter.Op)
	}
	for _, arg := range filter.Args {
		var level expression.Level
		switch term := arg.(type) {
		case *expression.Call:
			if err := c.EnsureSupported(term); err != nil {
				return err
			}
			continue
		case *expression.AttributeRef:
			level = term.Level
		case *expression.FieldRef:
			level = term.Level
		case *expression.NestedRef:
			level = term.Level
		default:
			// A constant carries nothing a Reader has to support.
			continue

View on GitHub (pinned to 806f444784)

Solutions

  1. Query the Reader's filter capabilities and restrict the expression to supported operators.
  2. Rewrite unsupported operators into supported equivalents (e.g. ranges into explicit comparisons if supported).
  3. Pre-validate the filter with EnsureSupported before calling the Reader.

Example fix

// before
caps := reader.FilterCapabilities()
if err := caps.EnsureSupported(filter); err != nil { ... } // discover first
// after: build filter only from operators in caps
if !caps.SupportsOperator(expression.OpGt) { filter = rewriteToEq(filter) }
Defensive patterns

Strategy: validation

Validate before calling

caps := reader.FilterCapabilities()
if err := caps.EnsureSupported(filter); err != nil {
  return fmt.Errorf("filter unsupported by reader: %w", err)
}

Try / catch

if err := reader.FindTraces(ctx, traces, q); err != nil {
  if errors.Is(err, tracestore.ErrFilterUnsupported) {
    filter = downgradeFilter(filter, caps) // rewrite to supported ops
  }
}

Prevention

When it happens

Trigger: Passing a filter containing an operator (e.g. OpGt, OpRegex) to a Reader whose FilterCapabilities.SupportsOperator returns false for it — directly or nested inside an AND/NOT tree.

Common situations: Querying a backend (e.g. legacy-shape stores) that only supports equality with a filter using range or regex operators; capability discovery was skipped and the operator assumption was wrong.

Related errors


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/73cd5d25532681e4. Report an issue: GitHub.