{"record":{"id":"3de7a7e3a9b93ba9","repo":"jaegertracing/jaeger","slug":"filter-argument-is-empty-a-call-argument-must-car","errorCode":null,"errorMessage":"filter argument is empty: a call argument must carry a call","messagePattern":"filter argument is empty: a call argument must carry a call","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/proto/expression/v1/convert.go","lineNumber":88,"sourceCode":"\t\t}, nil\n\tcase *Expression_Nested:\n\t\treturn &expression.NestedRef{\n\t\t\tLevel: expression.Level(term.Nested.GetLevel()),\n\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","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/proto/expression/v1/convert.go#L70-L106","documentation":"In toFilterExpression, an Expression_Call node whose Call field carries an argument term that decodes to nil produces this error: a filter call argument must actually contain a call, but the wire message had none. It guards the filter expression decoder against partially populated protobuf trees produced by an older or buggy encoder.","triggerScenarios":"decodeCall processes an Expression_Call whose argument list contains a term that, after nested decoding, yields nil — e.g. a call argument protobuf with no oneof variant set (all of attr, field, nested, scalar, list, call empty).","commonSituations":"Reading filter expressions serialized by a client that predates a proto change; manually constructed protobuf messages with unset oneof fields; corrupted or truncated filter payloads sent over the wire.","solutions":["Re-encode the filter expression with a current version of the expression proto/encoder so every call argument sets exactly one of attr/field/nested/scalar/list/call.","Check the sender for code paths that build an Expression_Call argument without assigning its oneof field.","Validate the payload client-side before sending; treat nil-decoding terms as send errors via ErrTermNotEncodable on the encode side."],"exampleFix":"// before (sender leaves oneof unset)\ncallArg := &exprv1.Expression{}\n// after (set a concrete variant)\ncallArg := &exprv1.Expression{Value: &exprv1.Expression_Scalar{Scalar: exprv1.NewIntValue(1)}}","handlingStrategy":"try-catch","validationCode":"for _, arg := range callTerm.Call.Args {\n    if arg == nil || arg.Value == nil {\n        return errors.New(\"call argument has no oneof set\")\n    }\n}","typeGuard":"func hasTerm(e *exprv1.Expression) bool { return e != nil && e.Value != nil }","tryCatchPattern":"node, err := decodeCall(callTerm.Call, depth+1)\nif err != nil {\n    return nil, fmt.Errorf(\"cannot decode filter call: %w\", err)\n}","preventionTips":["Always set exactly one oneof variant on every Expression before serializing.","Keep proto versions in sync between producer and consumer.","Encode-side round-trip tests to catch empty terms before the wire."],"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"}