{"record":{"id":"342f818d68b9276c","repo":"jaegertracing/jaeger","slug":"filter-argument-is-empty-exactly-one-of-attr-fie","errorCode":null,"errorMessage":"filter argument is empty: exactly one of attr, field, nested, scalar, list or call must be set","messagePattern":"filter argument is empty: exactly one of attr, field, nested, scalar, list or call must be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/proto/expression/v1/convert.go","lineNumber":92,"sourceCode":"\t\t}, nil\n\tcase *Expression_Scalar:\n\t\treturn toFilterConstant(term.Scalar)\n\tcase *Expression_List:\n\t\treturn &expression.List{\n\t\t\tValues: term.List.GetValues(),\n\t\t\tType:   expression.ValueType(term.List.GetType()),\n\t\t}, nil\n\tcase *Expression_Call:\n\t\tnested, err := decodeCall(term.Call, depth+1)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif nested == nil {\n\t\t\treturn nil, errors.New(\"filter argument is empty: a call argument must carry a call\")\n\t\t}\n\t\treturn nested, nil\n\tdefault:\n\t\treturn nil, errors.New(\"filter argument is empty: exactly one of attr, field, nested, scalar, list or call must be set\")\n\t}\n}\n\n// toFilterConstant reads a wire constant as the node that holds it. The type hint is optional and\n// authoritative when set (RFC 0005 §5.4), so an unhinted constant becomes the untyped node — a\n// duration or an instant among them, since the wire has no hint for either and what a spelling\n// like \"2s\" means is settled by the field it is compared against (expression.ResolveConstants).\nfunc toFilterConstant(scalar *Scalar) (expression.Expression, error) {\n\tvalue := scalar.GetValue()\n\tswitch valueType := expression.ValueType(scalar.GetType()); valueType {\n\tcase \"\":\n\t\treturn &expression.AnyValue{Value: value}, nil\n\tcase expression.ValueTypeString:\n\t\treturn &expression.StringValue{Value: value}, nil\n\tcase expression.ValueTypeInt:\n\t\tnumber, err := strconv.ParseInt(value, 10, 64)\n\t\tif err != nil {\n\t\t\treturn nil, errNotOfDeclaredType(value, valueType)","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/proto/expression/v1/convert.go#L74-L110","documentation":"The default branch of toFilterExpression fires when an Expression's oneof holds none of the recognized variants (attr, field, nested, scalar, list, call). The wire message is structurally an Expression but carries no term, so no filter node can be built. It is the catch-all against empty or unknown oneof cases.","triggerScenarios":"decodeCall encounters a term whose oneof value is unset (nil) or set to a variant this package version does not know; also any non-Call term falling through to default with no variant populated.","commonSituations":"Producer compiled against a newer expression proto with a variant the consumer doesn't understand; empty Expression structs serialized by mistake; hand-crafted test fixtures missing the oneof assignment.","solutions":["Ensure the encoder sets exactly one oneof variant on every Expression before serialization.","Align proto definitions and jaeger versions between sender and receiver so all variants are known.","Reject unencodable terms at encode time (fromFilterExpression returns ErrTermNotEncodable) instead of letting empty terms reach the wire."],"exampleFix":"// before\nexpr := &exprv1.Expression{}\n// after\nexpr := &exprv1.Expression{Value: &exprv1.Expression_Attr{Attr: &exprv1.Attribute{Key: \"service.name\"}}}","handlingStrategy":"validation","validationCode":"func validExpr(e *exprv1.Expression) bool {\n    switch v := e.GetValue().(type) {\n    case *exprv1.Expression_Attr, *exprv1.Expression_Field, *exprv1.Expression_Nested,\n        *exprv1.Expression_Scalar, *exprv1.Expression_List, *exprv1.Expression_Call:\n        _ = v\n        return true\n    default:\n        return false\n    }\n}","typeGuard":"func isKnownTerm(e *exprv1.Expression) bool {\n    return e != nil && e.Value != nil\n}","tryCatchPattern":"node, err := toFilterExpression(term, depth)\nif err != nil {\n    return nil, fmt.Errorf(\"filter expression invalid: %w\", err)\n}","preventionTips":["Validate oneof population before serializing.","Bump consumer version when producers add new expression variants.","Reject unknown/unset terms at encode time with ErrTermNotEncodable."],"tags":["protobuf","filter","decoding"],"backgroundTag":"malformed-proto-payload","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}