apache/pulsar · error
function returns a single value, but it does not implement e
Error message
function returns a single value, but it does not implement error
What it means
A single-value handler must return only an error (func(msg T) error), since with one output there is nowhere to put a result. Reflection checks handler.Out(0).Implements(errorType); returning any other single value fails registration in newFunction.
Source
Thrown at pulsar-function-go/pf/function.go:90
}
}
return handlerTakesContext, nil
}
func validateReturns(handler reflect.Type) error {
errorType := reflect.TypeOf((*error)(nil)).Elem()
switch {
case handler.NumOut() > 2:
return fmt.Errorf("function may not return more than two values")
case handler.NumOut() > 1:
if !handler.Out(1).Implements(errorType) {
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 {View on GitHub (pinned to 820761864e)
Solutions
- Return (T, error) instead of just T so the value is recognized as output.
- If the function has no meaningful output, return only error: func(msg T) error.
- Never return a bare non-error value; the framework treats lone error as a success-with-no-output contract.
- Adapt existing logic with a wrapper returning (result, nil).
Example fix
// before
func handle(ctx context.Context, msg []byte) []byte { ... }
// after
func handle(ctx context.Context, msg []byte) ([]byte, error) {
return transform(msg), nil
} Defensive patterns
Strategy: validation
Validate before calling
func singleReturnIsError(handler interface{}) bool {
t := reflect.TypeOf(handler)
errType := reflect.TypeOf((*error)(nil)).Elem()
return t.Kind() == reflect.Func && t.NumOut() == 1 && t.Out(0).Implements(errType)
} Type guard
func isErrOnlyHandler(handler interface{}) bool {
t := reflect.TypeOf(handler)
errType := reflect.TypeOf((*error)(nil)).Elem()
return t.Kind() == reflect.Func && t.NumOut() == 1 && t.Out(0).Implements(errType)
} Try / catch
f, err := pf.NewGoFunction(ctx, pf.GoFunction{
Handler: myHandler,
})
if err != nil {
if strings.Contains(err.Error(), "single value") {
log.Fatalf("single-return handler must return only error: %v", err)
}
log.Fatalf("function registration failed: %v", err)
} Prevention
- If the handler produces output, always return (T, error) — never a bare T.
- Reserve the one-return form strictly for error-only (sink-like) functions.
- Add a compile-adjacent unit test that instantiates the function object.
- Document each handler's signature convention in your function package README.
When it happens
Trigger: Registering func(msg []byte) []byte or func(ctx context.Context, msg []byte) string — NumOut()==1 but the sole return type does not implement error.
Common situations: Writing map-style handlers that return only the transformed value, assuming return-only-value signatures are supported; forgetting to return an error alongside the result; porting from frameworks that accept bare-value handlers.
Related errors
- function returns two values, but the second does not impleme
- 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
- The specified go executable binary does not exist
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/7f07c0f5550e4ba0.
Report an issue: GitHub.