{"record":{"id":"e6daea4e2400fbe6","repo":"apache/pulsar","slug":"function-is-nil","errorCode":null,"errorMessage":"function is nil","messagePattern":"function is nil","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pulsar-function-go/pf/function.go","lineNumber":99,"sourceCode":"\tswitch {\n\tcase handler.NumOut() > 2:\n\t\treturn fmt.Errorf(\"function may not return more than two values\")\n\tcase handler.NumOut() > 1:\n\t\tif !handler.Out(1).Implements(errorType) {\n\t\t\treturn fmt.Errorf(\"function returns two values, but the second does not implement error\")\n\t\t}\n\tcase handler.NumOut() == 1:\n\t\tif !handler.Out(0).Implements(errorType) {\n\t\t\treturn fmt.Errorf(\"function returns a single value, but it does not implement error\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc newFunction(inputFunc interface{}) function {\n\tif inputFunc == nil {\n\t\treturn errorHandler(fmt.Errorf(\"function is nil\"))\n\t}\n\thandler := reflect.ValueOf(inputFunc)\n\thandlerType := reflect.TypeOf(inputFunc)\n\tif handlerType.Kind() != reflect.Func {\n\t\treturn errorHandler(fmt.Errorf(\"function kind %s is not %s\", handlerType.Kind(), reflect.Func))\n\t}\n\n\ttakesContext, err := validateArguments(handlerType)\n\tif err != nil {\n\t\treturn errorHandler(err)\n\t}\n\n\tif err := validateReturns(handlerType); err != nil {\n\t\treturn errorHandler(err)\n\t}\n\n\treturn pulsarFunction(func(ctx context.Context, input []byte) ([]byte, error) {\n\t\t// construct arguments","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-function-go/pf/function.go#L81-L117","documentation":"pulsar-function-go wraps the user-supplied Go function into an internal `function` interface via newFunction. If the value passed to pf.Start() is nil, no valid handler can be built, so the library returns an errorHandler function that always yields this error instead of panicking at construction time. The failure surfaces when the instance actually starts and tries to process messages.","triggerScenarios":"Calling pf.Start(nil), or passing a nil func variable (e.g. a func obtained from config/flag that was never assigned).","commonSituations":"A variable holding the handler is conditionally assigned; a refactor renamed the handler function leaving a nil default; loading the handler dynamically and the lookup returned nil.","solutions":["Pass a non-nil function literal or named function to pf.Start(myFunc).","Check the variable holding your handler before calling Start: if myFunc == nil { log.Fatal(...) }.","If the handler comes from dynamic dispatch, ensure the registration/assignment path runs before Start."],"exampleFix":"// before\nvar handler func(context.Context, []byte) ([]byte, error)\npf.Start(handler) // nil -> \"function is nil\"\n// after\nvar handler func(context.Context, []byte) ([]byte, error) = actualHandler\nif handler == nil {\n    log.Fatal(\"no function handler configured\")\n}\npf.Start(handler)","handlingStrategy":"validation","validationCode":"if fn == nil {\n    return fmt.Errorf(\"handler must be a non-nil func before calling pf.Start\")\n}\npf.Start(fn)","typeGuard":"func isFunc(v interface{}) bool {\n    return v != nil && reflect.TypeOf(v).Kind() == reflect.Func\n}","tryCatchPattern":null,"preventionTips":["Always pass a named function or function literal directly to pf.Start.","Initialize handler variables at declaration, not lazily.","Add a unit test asserting the handler variable is non-nil before startup."],"tags":["go","function-registry","nil-value","startup"],"backgroundTag":"nil-function-handler","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}