jaegertracing/jaeger · error
%w: it can carry only one predicate on %q
Error message
%w: it can carry only one predicate on %q
What it means
Each legacy scalar field holds a single value: one entry per attribute key, one ServiceName, one OperationName, one DurationMin and one DurationMax. When the filter's flat conjunction contains two predicates on the same field — the same attribute key twice, two service-name equalities, two min bounds — the second cannot be stored, so applyAttribute/applyText/applyDurationBound refuse it with ErrFilterUnsupported naming the field. Note this occurs even when the two predicates are identical, since AND-ing equal predicates still needs two slots.
Source
Thrown at internal/storage/v2/api/tracestore/shape.go:295
func errNotADuration(name string, value expression.Expression) error {
if constant, ok := value.(*expression.AnyValue); ok {
return fmt.Errorf("%w: the bound %q on %q was never read as a duration",
ErrFilterInvalid, constant.Value, name)
}
return fmt.Errorf(`%w: it compares %q against a duration such as "2s" only`,
ErrFilterUnsupported, name)
}
func errUnsupportedOperator(op expression.Operator) error {
return fmt.Errorf("%w: it does not support the operator %q", ErrFilterUnsupported, op)
}
func errUnsupportedOperatorOn(op expression.Operator, name string) error {
return fmt.Errorf("%w: it does not support the operator %q on %q", ErrFilterUnsupported, op, name)
}
func errRepeatedPredicateOn(name string) error {
return fmt.Errorf("%w: it can carry only one predicate on %q", ErrFilterUnsupported, name)
}
View on GitHub (pinned to 806f444784)
Solutions
- Deduplicate predicates on the same field before building the filter; keep only one per field/key.
- Express multiple allowed values via an IN-style construct or issue one query per value and merge results.
- Target a backend with native filter support where repeated predicates are conjoined natively.
Example fix
// before
preds := []Expression{eq("service.name","a"), eq("service.name","a")} // duplicate
// after — dedupe before building the conjunction
seen := map[string]bool{}; var unique []Expression
for _, p := range preds { key := refKeyOf(p); if !seen[key] { seen[key] = true; unique = append(unique, p) } } Defensive patterns
Strategy: validation
Validate before calling
func dedupePredicates(preds []*expression.Call) []*expression.Call {
seen := map[string]bool{}; out := preds[:0]
for _, p := range preds {
key := fmt.Sprintf("%T|%v", p.Args[0], p.Args[0])
k2 := refKey(p) // e.g. attribute key or level+name
if seen[k2] { continue }
seen[k2] = true; out = append(out, p)
}
return out
} Try / catch
legacy, err := params.ToLegacyShape()
if errors.Is(err, tracestore.ErrFilterUnsupported) {
return nil, fmt.Errorf("only one predicate per field is supported: %w", err)
} Prevention
- Deduplicate filter conditions per field/key before building the query
- Merge duplicate UI filter chips into one condition
- Issue one query per alternative value instead of repeating the field
When it happens
Trigger: ToLegacyShape() processes a conjunction containing two OpEq predicates on the same attribute key, two equalities on span.name or resource.service, or two OpGte (or two OpLte) bounds on span.duration.
Common situations: A UI accumulates duplicate filter chips without deduplication; query builders append the same condition twice; users express name in ('a','b') as two name == predicates, which OR semantics cannot map onto one legacy slot.
Related errors
- %w: it does not support the built-in field %q of the %q leve
- %w: it compares %q against a string constant only
- %w: it compares %q against a duration such as "2s" only
- %w: it does not support the operator %q
- %w: it does not support the operator %q on %q
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/1f4ad8e81f91ecc8.
Report an issue: GitHub.