jaegertracing/jaeger · error · ErrFilterUnsupported
%w: it compares a reference against a constant only
Error message
%w: it compares a reference against a constant only
What it means
applyAsLegacyField converts a predicate Call into a legacy TraceQueryParams field. The predicate's first argument must be an AttributeRef or FieldRef; anything else (e.g. a constant on the left, a nested Call) is not a comparable reference and yields ErrFilterUnsupported with 'compares a reference against a constant only'.
Source
Thrown at internal/storage/v2/api/tracestore/shape.go:175
default:
return []*expression.Call{filter}, nil
}
}
// applyAsLegacyField writes one predicate into the legacy field that carries it. A legacy field
// holds a key and one value, so a predicate that reads no single value off the span — a
// quantifier over the events, an operator applied to a call — has nowhere to go.
func applyAsLegacyField(query *TraceQueryParams, predicate *expression.Call) error {
if len(predicate.Args) != 2 {
return errUnsupportedOperator(predicate.Op)
}
switch ref := predicate.Args[0].(type) {
case *expression.AttributeRef:
return applyAttribute(query, predicate.Op, ref, predicate.Args[1])
case *expression.FieldRef:
return applyField(query, predicate.Op, ref, predicate.Args[1])
default:
return fmt.Errorf("%w: it compares a reference against a constant only", ErrFilterUnsupported)
}
}
func applyAttribute(query *TraceQueryParams, op expression.Operator, ref *expression.AttributeRef, value expression.Expression) error {
if op != expression.OpEq {
return errUnsupportedOperatorOn(op, ref.Key)
}
if !legacyFilterLevels.SupportsLevel(ref.Level) {
return fmt.Errorf("%w: it does not index the %q level", ErrFilterUnsupported, ref.Level)
}
text, err := textConstant(ref.Key, value)
if err != nil {
return err
}
if _, ok := query.Attributes.Get(ref.Key); ok {
return errRepeatedPredicateOn(ref.Key)
}
query.Attributes.PutStr(ref.Key, text)View on GitHub (pinned to 806f444784)
Solutions
- Rewrite the comparison so the reference (attribute or field) is the first operand and the constant the second.
- Use a filter-based Reader path instead of the legacy shape if you need general comparisons.
- Pre-validate predicate argument order before conversion.
Example fix
// before
expression.Eq(expression.Constant("svc"), expression.SpanAttribute("service.name"))
// after
expression.Eq(expression.SpanAttribute("service.name"), expression.Constant("svc")) Defensive patterns
Strategy: validation
Validate before calling
func refFirst(c *expression.Call) bool {
switch c.Args[0].(type) {
case *expression.AttributeRef, *expression.FieldRef:
return true
}
return false
}
// ensure all predicates pass before conversion Type guard
func asRef(e expression.Expression) (expression.Expression, bool) {
switch e.(type) {
case *expression.AttributeRef, *expression.FieldRef:
return e, true
}
return nil, false
} Try / catch
shape, err := tracestore.ToLegacyShape(filter)
if err != nil {
if errors.Is(err, tracestore.ErrFilterUnsupported) && strings.Contains(err.Error(), "constant") {
filter = normalizeOperandOrder(filter)
}
} Prevention
- Always put the attribute/field reference as the first operand of comparisons.
- Use typed constructors (Eq(ref, constant)) that enforce operand order.
- Lint filter builders for constant-first comparisons.
When it happens
Trigger: Calling ToLegacyShape with a predicate whose Args[0] is neither *expression.AttributeRef nor *expression.FieldRef — e.g. constant-first comparisons or function-call operands.
Common situations: Filters built with reversed operand order (constant == attribute) or with computed expressions on the left side, then converted to the legacy query shape which only supports ref-vs-constant comparisons.
Related errors
- %w: it evaluates a conjunction of predicates only
- %w: it does not index the %q level
- %w: it does not support the operator %q
- %w: it does not index the %q level
- filter argument is empty: a call argument must carry a call
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/a1671b2dbf052fc2.
Report an issue: GitHub.