{"record":{"id":"a7db1af46099e647","repo":"apache/pulsar","slug":"function-kind-s-is-not-s","errorCode":null,"errorMessage":"function kind %s is not %s","messagePattern":"function kind (.+?) is not (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pulsar-function-go/pf/function.go","lineNumber":104,"sourceCode":"\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\n\t\tvar args []reflect.Value\n\t\tif takesContext {\n\t\t\targs = append(args, reflect.ValueOf(ctx))\n\t\t}\n","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-function-go/pf/function.go#L86-L122","documentation":"newFunction uses reflection to verify that the value passed to pf.Start() is actually a func. If Start receives any other kind of value (string, struct, int, etc.), the library returns an errorHandler that produces this formatted error, naming the offending reflect.Kind.","triggerScenarios":"Calling pf.Start() with a non-func value, e.g. pf.Start(\"myHandler\") or pf.Start(someStruct), or an untyped nil interface wrapped in a struct field.","commonSituations":"Config-driven dispatch where the wrong variable is passed (config value instead of the function); type changes after refactors; misunderstanding that Start expects the function itself, not its name.","solutions":["Pass the function itself, not a string name or struct: pf.Start(myFunc).","Verify the argument's Go type is a func before calling Start.","If dispatching by name, resolve the name to a func value first (e.g. a map[string]func(...))."],"exampleFix":"// before\npf.Start(\"myHandler\") // kind string is not func\n// after\npf.Start(myHandler)","handlingStrategy":"validation","validationCode":"if reflect.TypeOf(arg) == nil || reflect.TypeOf(arg).Kind() != reflect.Func {\n    return fmt.Errorf(\"pf.Start requires a func, got %T\", arg)\n}\npf.Start(arg)","typeGuard":"func isFuncValue(v interface{}) bool {\n    t := reflect.TypeOf(v)\n    return t != nil && t.Kind() == reflect.Func\n}","tryCatchPattern":null,"preventionTips":["Pass the function value itself, never its name as a string.","Keep handler types explicit in config structs (func fields, not interface{}).","Cover dispatch paths with a test that invokes Start in a subprocess."],"tags":["go","reflection","type-mismatch","startup"],"backgroundTag":"invalid-handler-type","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"}