{"record":{"id":"dbfcbbca62ab9382","repo":"apache/beam","slug":"bad-encoding-function","errorCode":null,"errorMessage":"bad encoding function","messagePattern":"bad encoding function","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/graphx/serialize.go","lineNumber":144,"sourceCode":"\t\tt, err := decodeFullType(out.Type)\n\t\tif err != nil {\n\t\t\twrapped := errors.Wrap(err, \"bad output type\")\n\t\t\treturn \"\", nil, nil, nil, nil, errors.WithContextf(wrapped, \"decoding userfn %v\", edge)\n\t\t}\n\t\toutbound = append(outbound, &graph.Outbound{Type: t})\n\t}\n\n\treturn opcode, u, wfn, inbound, outbound, nil\n}\n\nfunc encodeCustomCoder(c *coder.CustomCoder) (*v1pb.CustomCoder, error) {\n\tt, err := encodeType(c.Type)\n\tif err != nil {\n\t\treturn nil, errors.WithContextf(err, \"encoding custom coder %v for type %v\", c, c.Type)\n\t}\n\tenc, err := encodeUserFn(c.Enc)\n\tif err != nil {\n\t\twrapped := errors.Wrap(err, \"bad encoding function\")\n\t\treturn nil, errors.WithContextf(wrapped, \"encoding custom coder %v\", c)\n\t}\n\tdec, err := encodeUserFn(c.Dec)\n\tif err != nil {\n\t\twrapped := errors.Wrap(err, \"bad decoding function\")\n\t\treturn nil, errors.WithContextf(wrapped, \"encoding custom coder %v\", c)\n\t}\n\n\tret := &v1pb.CustomCoder{\n\t\tName: c.Name,\n\t\tType: t,\n\t\tEnc:  enc,\n\t\tDec:  dec,\n\t}\n\treturn ret, nil\n}\n\nfunc decodeCustomCoder(c *v1pb.CustomCoder) (*coder.CustomCoder, error) {","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/graphx/serialize.go#L126-L162","documentation":"encodeCustomCoder serializes a coder.CustomCoder, calling encodeUserFn on its encoding function c.Enc. If the encoding function cannot be represented as a serializable user function (e.g. it is a closure, a non-top-level function, or defined in a package that cannot be resolved), the error is wrapped as \"bad encoding function\". Beam requires custom coder functions to be named, top-level functions in a registered package.","triggerScenarios":"Creating a coder.NewCustomCoder whose enc function is an anonymous/closure function, a method value, or a function in an internal/unregistered package, then calling Add or EncodeCoderRef to serialize the coder.","commonSituations":"Passing inline func literals to NewCustomCoder; using methods bound to an instance; defining coders in test binaries or generated code that cannot be referenced by name at decode time.","solutions":["Define the encoding function as a named, package-level function","Avoid closures, bound methods, and anonymous funcs in custom coders","Verify encodeUserFn can resolve the function's fully qualified name (use reflectx.FunctionName to test)","Move coder functions out of test/generated code into a stable package"],"exampleFix":"// before\nenc := func(v T) []byte { ... }\nc, _ := coder.NewCustomCoder(\"myCoder\", typ, enc, dec)\n// after\nfunc encodeT(v T) []byte { ... }\nc, _ := coder.NewCustomCoder(\"myCoder\", typ, encodeT, decodeT)","handlingStrategy":"type-guard","validationCode":"func isValidCoderFn(f interface{}) bool {\n\tv := reflect.ValueOf(f)\n\treturn v.Kind() == reflect.Func && v.Pointer() != 0 &&\n\t\truntime.IsFunction(v) && !isClosureOrMethodValue(v)\n}","typeGuard":"func isNamedFunc(f interface{}) bool {\n\tname := reflectx.FunctionName(f)\n\treturn name != \"\" && !strings.Contains(name, \"func\") && !strings.Contains(name, \"-\")\n}","tryCatchPattern":"ref, err := graphx.EncodeCoderRef(c)\nif err != nil && strings.Contains(err.Error(), \"bad encoding function\") {\n\treturn fmt.Errorf(\"coder %v uses non-serializable enc fn: %w\", c, err)\n}","preventionTips":["Only use package-level named functions in coder.NewCustomCoder","Never use closures or method values as coder enc/dec","Define coders in stable, importable packages","Add a unit test that encodes every custom coder you ship"],"tags":["go","beam","coder","serialization"],"backgroundTag":"unsupported-function-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}