{"record":{"id":"73cd5d25532681e4","repo":"jaegertracing/jaeger","slug":"w-it-does-not-support-the-operator-q","errorCode":null,"errorMessage":"%w: it does not support the operator %q","messagePattern":"%w: it does not support the operator %q","errorType":"validation","errorClass":"ErrFilterUnsupported","httpStatus":null,"severity":"error","filePath":"internal/storage/v2/api/tracestore/admission.go","lineNumber":74,"sourceCode":"// caller's to settle first.\nfunc (q TraceQueryParams) ForCapabilities(caps SearchCapabilities) (TraceQueryParams, error) {\n\tif q.Filter == nil {\n\t\treturn q, nil\n\t}\n\tif caps.Filter.IsEmpty() {\n\t\treturn q.ToLegacyShape()\n\t}\n\treturn q, caps.Filter.EnsureSupported(q.Filter)\n}\n\n// EnsureSupported walks the filter and refuses the first predicate the Reader did not declare it\n// can evaluate.\nfunc (c FilterCapabilities) EnsureSupported(filter *expression.Call) error {\n\tif filter == nil {\n\t\treturn nil\n\t}\n\tif !c.SupportsOperator(filter.Op) {\n\t\treturn fmt.Errorf(\"%w: it does not support the operator %q\", ErrFilterUnsupported, filter.Op)\n\t}\n\tfor _, arg := range filter.Args {\n\t\tvar level expression.Level\n\t\tswitch term := arg.(type) {\n\t\tcase *expression.Call:\n\t\t\tif err := c.EnsureSupported(term); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcontinue\n\t\tcase *expression.AttributeRef:\n\t\t\tlevel = term.Level\n\t\tcase *expression.FieldRef:\n\t\t\tlevel = term.Level\n\t\tcase *expression.NestedRef:\n\t\t\tlevel = term.Level\n\t\tdefault:\n\t\t\t// A constant carries nothing a Reader has to support.\n\t\t\tcontinue","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/api/tracestore/admission.go#L56-L92","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Query the Reader's filter capabilities and restrict the expression to supported operators.","Rewrite unsupported operators into supported equivalents (e.g. ranges into explicit comparisons if supported).","Pre-validate the filter with EnsureSupported before calling the Reader."],"exampleFix":"// before\ncaps := reader.FilterCapabilities()\nif err := caps.EnsureSupported(filter); err != nil { ... } // discover first\n// after: build filter only from operators in caps\nif !caps.SupportsOperator(expression.OpGt) { filter = rewriteToEq(filter) }","handlingStrategy":"validation","validationCode":"caps := reader.FilterCapabilities()\nif err := caps.EnsureSupported(filter); err != nil {\n  return fmt.Errorf(\"filter unsupported by reader: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := reader.FindTraces(ctx, traces, q); err != nil {\n  if errors.Is(err, tracestore.ErrFilterUnsupported) {\n    filter = downgradeFilter(filter, caps) // rewrite to supported ops\n  }\n}","preventionTips":["Always read FilterCapabilities before constructing filters.","Write filter builders parameterized on the capability set.","Unit-test filters against each backend's declared capabilities."],"tags":["filter","validation","tracestore"],"backgroundTag":"unsupported-filter-operator","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}