{"record":{"id":"cb7600261a968d83","repo":"jaegertracing/jaeger","slug":"w-it-cannot-be-combined-with-v-express-those-p","errorCode":null,"errorMessage":"%w: it cannot be combined with %v; express those predicates in the filter instead","messagePattern":"%w: it cannot be combined with (.+?); express those predicates in the filter instead","errorType":"validation","errorClass":"ErrFilterInvalid","httpStatus":null,"severity":"error","filePath":"internal/storage/v2/api/tracestore/admission.go","lineNumber":45,"sourceCode":"\tif q.ServiceName != \"\" {\n\t\tset = append(set, \"service_name\")\n\t}\n\tif q.OperationName != \"\" {\n\t\tset = append(set, \"operation_name\")\n\t}\n\tif q.DurationMin != 0 {\n\t\tset = append(set, \"duration_min\")\n\t}\n\tif q.DurationMax != 0 {\n\t\tset = append(set, \"duration_max\")\n\t}\n\tif q.Attributes != (pcommon.Map{}) && q.Attributes.Len() > 0 {\n\t\tset = append(set, \"attributes\")\n\t}\n\tif len(set) == 0 {\n\t\treturn nil\n\t}\n\treturn fmt.Errorf(\"%w: it cannot be combined with %v; express those predicates in the filter instead\",\n\t\tErrFilterInvalid, set)\n}\n\n// ForCapabilities gives the Reader whichever of the two filtering models it declared it can\n// evaluate. A Reader that declares filter support gets the filter itself, once every level and\n// operator it uses is one that Reader listed. A Reader that declares none gets the filter rewritten\n// into the legacy predicate fields, which carry the equalities and inclusive duration bounds and\n// nothing else (ToLegacyShape), or a refusal where they cannot carry it.\n//\n// It answers only that question. Whether the request is one this deployment accepts at all is the\n// 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}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/v2/api/tracestore/admission.go#L27-L63","documentation":"EnsureFilterStandsAlone validates that a TraceQueryParams does not set legacy query fields (service, operation, tags, duration/minDuration, startTime/endTime, attributes) together with a filter expression. If both are present it returns ErrFilterInvalid wrapped with the list of offending fields, because the two filtering models would over-constrain the query.","triggerScenarios":"Calling a v2 trace Reader's FindTraceIDs/FindTraces with a TraceQueryParams whose ServiceName/Operation/Attributes/TimeRange etc. are non-zero while a filter Call is also supplied, e.g. via prepareSearchQuery or toTraceQueryParams paths.","commonSituations":"Migrating code from the legacy query API to filter expressions while keeping old field assignments; UI/API layers that build both forms of predicates unconditionally.","solutions":["Move every legacy predicate into the filter expression and clear the legacy fields.","If you only need legacy matching, drop the filter entirely.","Pre-validate with EnsureFilterStandsAlone before invoking the Reader."],"exampleFix":"// before\nquery := tracestore.TraceQueryParams{ServiceName: \"svc\", Filter: expr}\n// after\nquery := tracestore.TraceQueryParams{\n  Filter: expression.And(\n    expression.Eq(expression.SpanAttribute(\"service.name\"), \"svc\"),\n    expr,\n  ),\n}","handlingStrategy":"validation","validationCode":"if err := tracestore.EnsureFilterStandsAlone(query.Filter); err != nil {\n  return fmt.Errorf(\"invalid query: %w\", err)\n}\n// also zero out legacy fields when a filter is set\nif query.Filter != nil {\n  query.ServiceName, query.Operation = \"\", \"\"\n  query.Attributes = pcommon.NewMap()\n}","typeGuard":null,"tryCatchPattern":"if err := reader.FindTraces(ctx, traces, query); err != nil {\n  if errors.Is(err, tracestore.ErrFilterInvalid) {\n    return fmt.Errorf(\"legacy fields conflict with filter: %w\", err)\n  }\n  return err\n}","preventionTips":["Build queries through a single helper that emits either legacy fields or a filter, never both.","When migrating to filters, delete legacy field assignments in the same change.","Call EnsureFilterStandsAlone in tests for query builders."],"tags":["query","validation","tracestore"],"backgroundTag":"conflicting-query-parameters","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}