apache/pulsar · critical
function kind %s is not %s
Error message
function kind %s is not %s
What it means
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.
Source
Thrown at pulsar-function-go/pf/function.go:104
return fmt.Errorf("function returns two values, but the second does not implement error")
}
case handler.NumOut() == 1:
if !handler.Out(0).Implements(errorType) {
return fmt.Errorf("function returns a single value, but it does not implement error")
}
}
return nil
}
func newFunction(inputFunc interface{}) function {
if inputFunc == nil {
return errorHandler(fmt.Errorf("function is nil"))
}
handler := reflect.ValueOf(inputFunc)
handlerType := reflect.TypeOf(inputFunc)
if handlerType.Kind() != reflect.Func {
return errorHandler(fmt.Errorf("function kind %s is not %s", handlerType.Kind(), reflect.Func))
}
takesContext, err := validateArguments(handlerType)
if err != nil {
return errorHandler(err)
}
if err := validateReturns(handlerType); err != nil {
return errorHandler(err)
}
return pulsarFunction(func(ctx context.Context, input []byte) ([]byte, error) {
// construct arguments
var args []reflect.Value
if takesContext {
args = append(args, reflect.ValueOf(ctx))
}
View on GitHub (pinned to 820761864e)
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(...)).
Example fix
// before
pf.Start("myHandler") // kind string is not func
// after
pf.Start(myHandler) Defensive patterns
Strategy: validation
Validate before calling
if reflect.TypeOf(arg) == nil || reflect.TypeOf(arg).Kind() != reflect.Func {
return fmt.Errorf("pf.Start requires a func, got %T", arg)
}
pf.Start(arg) Type guard
func isFuncValue(v interface{}) bool {
t := reflect.TypeOf(v)
return t != nil && t.Kind() == reflect.Func
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot load Pulsar Client Implementation:
- does not implement
- functions may not take more than two arguments, but function
- function takes two arguments, but the first is not Context.
- function may not return more than two values
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/a7db1af46099e647.
Report an issue: GitHub.