{"record":{"id":"311173b4364632b6","repo":"jaegertracing/jaeger","slug":"w-it-does-not-support-the-operator-q-on-q","errorCode":null,"errorMessage":"%w: it does not support the operator %q on %q","messagePattern":"%w: it does not support the operator %q on %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/v2/api/tracestore/shape.go","lineNumber":291,"sourceCode":"\n// errNotADuration refuses a bound that is not a length of time. An untyped constant reaching here\n// was never read as a duration, which expression.ResolveConstants does on the way in, so the\n// refusal says that rather than blaming the spelling the caller wrote.\nfunc errNotADuration(name string, value expression.Expression) error {\n\tif constant, ok := value.(*expression.AnyValue); ok {\n\t\treturn fmt.Errorf(\"%w: the bound %q on %q was never read as a duration\",\n\t\t\tErrFilterInvalid, constant.Value, name)\n\t}\n\treturn fmt.Errorf(`%w: it compares %q against a duration such as \"2s\" only`,\n\t\tErrFilterUnsupported, name)\n}\n\nfunc errUnsupportedOperator(op expression.Operator) error {\n\treturn fmt.Errorf(\"%w: it does not support the operator %q\", ErrFilterUnsupported, op)\n}\n\nfunc errUnsupportedOperatorOn(op expression.Operator, name string) error {\n\treturn fmt.Errorf(\"%w: it does not support the operator %q on %q\", ErrFilterUnsupported, op, name)\n}\n\nfunc errRepeatedPredicateOn(name string) error {\n\treturn fmt.Errorf(\"%w: it can carry only one predicate on %q\", ErrFilterUnsupported, name)\n}\n","sourceCodeStart":273,"sourceCodeEnd":297,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/api/tracestore/shape.go#L273-L297","documentation":"The legacy fields a filter is downconverted into accept exactly one operator each: attributes, service name and operation name accept only equality (OpEq), and span.duration accepts only inclusive bounds OpGte/OpLte. Any other operator on that field — e.g. != on a tag, > on a name, < on a duration — has no legacy representation and is refused with ErrFilterUnsupported naming the operator and field. The narrower errUnsupportedOperator variant is used when no field name is known.","triggerScenarios":"ToLegacyShape() sees an AttributeRef predicate with op != OpEq; a service/name FieldRef predicate with op != OpEq; or a duration FieldRef predicate with an op other than OpGte/OpLte.","commonSituations":"Users write attribute != value or attribute > value searches in a UI; exclusive bounds duration > 1s are requested from a legacy backend; a filter builder emits regex-like operators unsupported by the legacy shape.","solutions":["Rewrite as equality where possible (e.g. negate client-side, or use the exact matching value).","Use inclusive bounds for duration: duration >= X / duration <= Y instead of strict > / <.","Target a backend that declares native filter/operator support so no downconversion happens."],"exampleFix":"// before\n&expression.Call{Op: expression.OpGt, Args: []expression.Expression{durField, &expression.DurationValue{Value: time.Second}}}\n// after\n&expression.Call{Op: expression.OpGte, Args: []expression.Expression{durField, &expression.DurationValue{Value: time.Second}}}","handlingStrategy":"validation","validationCode":"func allowedOp(op expression.Operator, ref expression.Expression) bool {\n  switch ref.(type) {\n  case *expression.AttributeRef:\n    return op == expression.OpEq\n  case *expression.FieldRef:\n    fr := ref.(*expression.FieldRef)\n    if fr.Name == expression.SpanFieldDuration {\n      return op == expression.OpGte || op == expression.OpLte\n    }\n    return op == expression.OpEq\n  }\n  return false\n}","typeGuard":null,"tryCatchPattern":"legacy, err := params.ToLegacyShape()\nif errors.Is(err, tracestore.ErrFilterUnsupported) {\n  return nil, fmt.Errorf(\"legacy fields support only =, and >=/<= for duration: %w\", err)\n}","preventionTips":["Use equality for attributes, service and operation names","Use inclusive >= / <= for duration bounds","Offer exclusive-bound and negation features only where the backend declares support"],"tags":["jaeger","tracestore","filter-unsupported","operator"],"backgroundTag":"unsupported-query-operator","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}