{"record":{"id":"ed7e4a662cfdaa42","repo":"jaegertracing/jaeger","slug":"w-it-does-not-support-the-built-in-field-q-of-t","errorCode":null,"errorMessage":"%w: it does not support the built-in field %q of the %q level","messagePattern":"%w: it does not support the built-in field %q of the %q level","errorType":"validation","errorClass":"ErrFilterUnsupported","httpStatus":null,"severity":"error","filePath":"internal/storage/v2/api/tracestore/shape.go","lineNumber":208,"sourceCode":"\tif _, ok := query.Attributes.Get(ref.Key); ok {\n\t\treturn errRepeatedPredicateOn(ref.Key)\n\t}\n\tquery.Attributes.PutStr(ref.Key, text)\n\treturn nil\n}\n\n// applyField writes a predicate on a built-in field into the legacy field that holds it. Only\n// three of the built-ins have one, and a predicate on any of the others is refused.\nfunc applyField(query *TraceQueryParams, op expression.Operator, ref *expression.FieldRef, value expression.Expression) error {\n\tswitch {\n\tcase isField(ref, expression.LevelResource, expression.ResourceFieldService):\n\t\treturn applyText(&query.ServiceName, op, ref.Name, value)\n\tcase isField(ref, expression.LevelSpan, expression.SpanFieldName):\n\t\treturn applyText(&query.OperationName, op, ref.Name, value)\n\tcase isField(ref, expression.LevelSpan, expression.SpanFieldDuration):\n\t\treturn applyDurationBound(query, op, ref.Name, value)\n\tdefault:\n\t\treturn fmt.Errorf(\"%w: it does not support the built-in field %q of the %q level\",\n\t\t\tErrFilterUnsupported, ref.Name, ref.Level)\n\t}\n}\n\n// isField reports whether the reference names that built-in field. It takes both the level and\n// the name because neither identifies a field on its own.\nfunc isField(ref *expression.FieldRef, level expression.Level, name string) bool {\n\treturn ref.Level == level && ref.Name == name\n}\n\n// applyText writes an equality on a string-valued legacy field.\nfunc applyText(target *string, op expression.Operator, name string, value expression.Expression) error {\n\tif op != expression.OpEq {\n\t\treturn errUnsupportedOperatorOn(op, name)\n\t}\n\ttext, err := textConstant(name, value)\n\tif err != nil {\n\t\treturn err","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/api/tracestore/shape.go#L190-L226","documentation":"When a TraceQueryParams carries a Filter but the Reader does not support filters, the query is rewritten into the legacy scalar fields (service name, operation name, duration bounds, attribute map). Only three built-in fields have a legacy equivalent; a predicate on any other built-in field (e.g. span status, span kind, event count) has nowhere to go and is refused with ErrFilterUnsupported wrapping this message. This is a static capability limit of the legacy-shape fallback, not a data or configuration problem.","triggerScenarios":"Calling TraceQueryParams.ToLegacyShape() (directly or via a Reader lacking filter support) with a Filter whose flat conjunction contains a *expression.FieldRef predicate whose (Level, Name) is not (LevelResource, service), (LevelSpan, name), or (LevelSpan, duration) — e.g. span:status = 'error'.","commonSituations":"A query interceptor or UI builds a filter on a built-in field like span.status or span.kind assuming full field support; the backend only declares legacy scalar support; version drift where newer expression fields are sent to an older backend path.","solutions":["Rewrite the predicate as an AttributeRef or restrict the filter to the three supported built-in fields (resource service, span name, span duration).","Use a Reader/backend that declares native filter support so the filter is passed through instead of downconverted.","Handle errors.Is(err, tracestore.ErrFilterUnsupported) and surface a 'query not supported by this backend' message to the user instead of retrying."],"exampleFix":"// before\nfilter := &expression.Call{Op: expression.OpEq, Args: []expression.Expression{\n  &expression.FieldRef{Level: expression.LevelSpan, Name: expression.SpanFieldStatus},\n  &expression.StringValue{Value: \"error\"}}}\n// after\nfilter := &expression.Call{Op: expression.OpEq, Args: []expression.Expression{\n  &expression.AttributeRef{Key: \"error\", Level: expression.LevelSpan},\n  &expression.StringValue{Value: \"true\"}}}","handlingStrategy":"validation","validationCode":"func usesOnlyLegacyFields(f *expression.Call) bool {\n  preds, err := flatten(f)\n  if err != nil { return false }\n  for _, p := range preds {\n    ref, ok := p.Args[0].(*expression.FieldRef)\n    if !ok { continue }\n    ok = (ref.Level == expression.LevelResource && ref.Name == expression.ResourceFieldService) ||\n         (ref.Level == expression.LevelSpan && ref.Name == expression.SpanFieldName) ||\n         (ref.Level == expression.LevelSpan && ref.Name == expression.SpanFieldDuration)\n    if !ok { return false }\n  }\n  return true\n}","typeGuard":"func isLegacyFieldRef(e expression.Expression) bool {\n  ref, ok := e.(*expression.FieldRef)\n  if !ok { return false }\n  switch {\n  case ref.Level == expression.LevelResource && ref.Name == expression.ResourceFieldService: return true\n  case ref.Level == expression.LevelSpan && ref.Name == expression.SpanFieldName: return true\n  case ref.Level == expression.LevelSpan && ref.Name == expression.SpanFieldDuration: return true\n  }\n  return false\n}","tryCatchPattern":"qp, err := params.ToLegacyShape()\nif err != nil {\n  if errors.Is(err, tracestore.ErrFilterUnsupported) {\n    return fmt.Errorf(\"backend cannot serve this filter: %w\", err)\n  }\n  return err\n}","preventionTips":["Restrict filter builders to the three legacy built-in fields when the backend lacks native filter support","Check the Reader's filter capabilities before constructing advanced field predicates","Treat ErrFilterUnsupported as a capability error and surface it, never retry"],"tags":["jaeger","tracestore","filter-unsupported","query-shape"],"backgroundTag":"unsupported-query-filter","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}