{"record":{"id":"51bba4ec5b3ba215","repo":"jaegertracing/jaeger","slug":"filter-term-cannot-be-encoded-for-the-wire","errorCode":null,"errorMessage":"filter term cannot be encoded for the wire","messagePattern":"filter term cannot be encoded for the wire","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/proto/expression/v1/convert.go","lineNumber":207,"sourceCode":"\tcase *expression.Call:\n\t\tif term == nil {\n\t\t\tbreak\n\t\t}\n\t\tcall, err := ToProto(term)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn &Expression{Term: &Expression_Call{Call: call}}, nil\n\t}\n\tif scalar := fromFilterConstant(expr); scalar != nil {\n\t\treturn &Expression{Term: &Expression_Scalar{Scalar: scalar}}, nil\n\t}\n\treturn nil, fmt.Errorf(\"%w: %T\", ErrTermNotEncodable, expr)\n}\n\n// ErrTermNotEncodable is returned for a term ToProto has no wire form for: a nil one, or a type\n// this package does not know. Both mean the tree was not the finalized filter ToProto expects.\nvar ErrTermNotEncodable = errors.New(\"filter term cannot be encoded for the wire\")\n\n// fromFilterConstant writes a constant node as the wire's spelling plus the hint that fits it. A\n// duration and an instant have no hint of their own, so they travel as an unhinted constant in\n// the syntax the field they are compared against is written in — Go duration syntax and RFC 3339\n// — which is the spelling the receiving side reads them back from.\n// It returns nil for a term that is not a constant, and for a constant that holds nothing: a nil\n// pointer of a constant type reads through the Expression interface as a constant of that type, and\n// reading its value would panic. The caller answers a nil with ErrTermNotEncodable, which is what a\n// tree carrying one deserves.\nfunc fromFilterConstant(expr expression.Expression) *Scalar {\n\tswitch term := expr.(type) {\n\tcase *expression.AnyValue:\n\t\tif term == nil {\n\t\t\treturn nil\n\t\t}\n\t\treturn &Scalar{Value: term.Value}\n\tcase *expression.StringValue:\n\t\tif term == nil {","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/proto/expression/v1/convert.go#L189-L225","documentation":"ErrTermNotEncodable is a sentinel error wrapped with the offending Go type (%T) when fromFilterExpression meets a filter term it has no wire representation for: either a nil term or a Go type the package does not recognize. It signals the filter tree was not finalized into the shape ToProto expects.","triggerScenarios":"Calling ToProto on a filter expression containing a nil term or a term type outside the package's known set (e.g. an unfinalized/internal node type); tests TestToProto_RefusesATermItCannotWrite and TestQueryParametersRefuseAnUnsendableFilter exercise this.","commonSituations":"Passing a query filter tree built by hand or by an older API version directly to ToProto without running the finalization step; constructing query parameters with unsupported comparison nodes.","solutions":["Inspect the wrapped %T in the error and replace that term type with one of the supported finalized filter term types.","Run the filter tree through the package's finalization/normalization step before calling ToProto.","In callers, use errors.Is(err, exprv1.ErrTermNotEncodable) to detect this case and return a 400-style validation error to the user.","Check for nil terms in the tree before encoding."],"exampleFix":"// before\nif err != nil { return err }\n// after\nif err != nil {\n    if errors.Is(err, exprv1.ErrTermNotEncodable) {\n        return httperr.BadRequest(\"unsupported filter term\")\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"func encodable(t FilterTerm) bool { return t != nil && isSupportedTermType(t) }","typeGuard":"func isSupportedTerm(t any) bool {\n    switch t.(type) {\n    case nil:\n        return false\n    default:\n        return isFinalizedTerm(t)\n    }\n}","tryCatchPattern":"pb, err := ToProto(tree)\nif errors.Is(err, ErrTermNotEncodable) {\n    return fmt.Errorf(\"filter term %w; finalize the tree first\", err)\n}","preventionTips":["Finalize filter trees with the package's finalization step before ToProto.","Check for nil terms before encoding.","Use errors.Is against ErrTermNotEncodable to surface user-facing validation errors."],"tags":["filter","encoding","sentinel-error"],"backgroundTag":"unsupported-filter-term","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}