{"record":{"id":"6048dd0262fe5580","repo":"apache/beam","slug":"bad-decode","errorCode":null,"errorMessage":"bad decode","messagePattern":"bad decode","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/graph/coder/coder.go","lineNumber":159,"sourceCode":"}\n\n// NewCustomCoder creates a coder for the supplied parameters defining a\n// particular encoding strategy.\nfunc NewCustomCoder(id string, t reflect.Type, encode, decode any) (*CustomCoder, error) {\n\tif err := validateEncoder(t, encode); err != nil {\n\t\treturn nil, errors.WithContext(err, \"NewCustomCoder\")\n\t}\n\tenc, err := funcx.New(reflectx.MakeFunc(encode))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"bad encode\")\n\t}\n\tif err := validateDecoder(t, decode); err != nil {\n\t\treturn nil, errors.WithContext(err, \"NewCustomCoder\")\n\t}\n\n\tdec, err := funcx.New(reflectx.MakeFunc(decode))\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"bad decode\")\n\t}\n\n\tc := &CustomCoder{\n\t\tName: id,\n\t\tType: t,\n\t\tEnc:  enc,\n\t\tDec:  dec,\n\t}\n\treturn c, nil\n}\n\n// NewCustomCoderWithFuncs creates a CustomCoder from pre-wrapped\n// reflectx.Func values. This allows the caller to control the Name()\n// returned by each function — critical for closures inside Go generic\n// functions where the compiler assigns identical names to different\n// type instantiations.\nfunc NewCustomCoderWithFuncs(id string, t reflect.Type, enc, dec *funcx.Fn) *CustomCoder {\n\treturn &CustomCoder{","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/graph/coder/coder.go#L141-L177","documentation":"NewCustomCoder wraps any error from converting the decode function via funcx.New(reflectx.MakeFunc(decode)) with \"bad decode\". It means the decode function could not be converted into an internal callable — usually nil or not a function. It fires only after validateDecoder succeeds, so it indicates a structurally invalid function value.","triggerScenarios":"Passing a nil decode function or a non-function value as the decode parameter of NewCustomCoder.","commonSituations":"Declaring the decode func variable without initializing it, or swapping encode/decode arguments so the functions land in the wrong slots in a way funcx rejects.","solutions":["Ensure decode is a non-nil Go function with signature func([]byte) T (or compatible)","Check the encode/decode arguments are not swapped","Inspect the wrapped underlying error for the exact funcx failure"],"exampleFix":"// before\nvar decodeFn func([]byte) T\ncc, err := coder.NewCustomCoder(\"myCoder\", t, encodeFn, decodeFn)\n// after\ndecodeFn := func(b []byte) T { var v T; decodeInto(b, &v); return v }\ncc, err := coder.NewCustomCoder(\"myCoder\", t, encodeFn, decodeFn)","handlingStrategy":"validation","validationCode":"if decode == nil { return errors.New(\"decode must be a non-nil func\") }\nif rv := reflect.ValueOf(decode); rv.Kind() != reflect.Func { return fmt.Errorf(\"decode must be a func, got %v\", rv.Kind()) }","typeGuard":"func isFunc(v any) bool { return v != nil && reflect.ValueOf(v).Kind() == reflect.Func }","tryCatchPattern":null,"preventionTips":["Initialize decode functions before registration","Keep encode/decode adjacent in code so order errors are visible","Match the decode signature func([]byte) T exactly"],"tags":["go","beam","custom-coder","reflection"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}