apache/beam · error
not a function: %v
Error message
not a function: %v
What it means
Satisfy in sdks/go/pkg/beam/core/funcx/signature.go validates that a value satisfies the funcx function contract. When the argument is neither a *funcx.Fn nor a reflect Func kind, it reflects on the value and, if value.Kind() != reflect.Func, returns "not a function: %v". The library throws it because signature analysis (NumIn/NumOut/parameter types) is only possible on actual function values.
Source
Thrown at sdks/go/pkg/beam/core/funcx/signature.go:122
//
// foo : (context.Context, X) -> bool
// bar : (int) -> bool
//
// both would satisfy a signature of (context.Context?, int) -> bool. Only
// "foo" would satisfy (context.Context, string) -> bool and only "bar" would
// satisfy (int) -> bool.
func Satisfy(fn any, sig *Signature) error {
var in, out []reflect.Type
var typ reflect.Type
switch fx := fn.(type) {
case *Fn:
typ = fx.Fn.Type()
case reflectx.Func:
typ = fx.Type()
default:
value := reflect.ValueOf(fn)
if value.Kind() != reflect.Func {
return errors.Errorf("not a function: %v", value)
}
typ = value.Type()
}
for i := 0; i < typ.NumIn(); i++ {
in = append(in, typ.In(i))
}
for i := 0; i < typ.NumOut(); i++ {
out = append(out, typ.Out(i))
}
if len(in) < len(sig.Args) || len(out) < len(sig.Return) {
return errors.Errorf("not enough required parameters: %v", typ)
}
if len(in) > len(sig.Args)+len(sig.OptArgs) || len(out) > len(sig.Return)+len(sig.OptReturn) {
return errors.Errorf("too many parameters: %v", typ)
}
// (1) Create generic binding. If inconsistent, reject fn. We do not allowView on GitHub (pinned to 12126d8942)
Solutions
- Pass an actual function value: `fx.Satisfy(myFunc)` not `fx.Satisfy(myFunc())`.
- If you have a *funcx.Fn, pass it directly — it is accepted via the fx.Fn branch.
- Check for nil or shadowed variables holding the wrong value before calling Satisfy.
- Wrap with fx.MustSatisfy only in tests/init; prefer fx.Satisfy and handle the returned error in production paths.
Example fix
// before fn := buildFn() // returns bool, not a func fx.MustSatisfy(fn) // after fn := buildFn // the function value itself fx.MustSatisfy(fn)
Defensive patterns
Strategy: type-guard
Validate before calling
func requireFunc(v interface{}) error {
if v == nil {
return errors.New("fn is nil")
}
if _, ok := v.(*fx.Fn); ok {
return nil
}
if reflect.TypeOf(v).Kind() != reflect.Func {
return fmt.Errorf("%T is not a function", v)
}
return nil
} Type guard
func isFuncValue(v interface{}) bool {
if v == nil {
return false
}
if _, ok := v.(*fx.Fn); ok {
return true
}
return reflect.TypeOf(v).Kind() == reflect.Func
} Try / catch
defer func() {
if r := recover(); r != nil {
// MustSatisfy may panic on non-functions
err = fmt.Errorf("signature check failed: %v", r)
}
}()
// or avoid panic entirely:
if err := fx.Satisfy(fn); err != nil {
return fmt.Errorf("not a function: %w", err)
} Prevention
- Never call a function when you mean to pass it: drop the `()`.
- Check for nil before passing function-typed variables.
- Prefer fx.Satisfy (returns error) over fx.MustSatisfy outside tests and init.
- When a helper returns a callback, verify its return type is the func, not the result.
When it happens
Trigger: Calling fx.Satisfy / fx.MustSatisfy / validateEncoder-style helpers with a non-function value such as a struct, method value bound incorrectly, nil, a funcx.Fn-typed wrapper used in the wrong branch, or a variable that was expected to hold a function but holds its result (e.g. `fn := myFunc()` instead of `fn := myFunc`).
Common situations: Passing a closure's invocation result instead of the closure itself; passing a method call `obj.Method` written as `obj.Method()`; handing a nil interface to MustSatisfy in an init path; type confusion after refactoring a helper that returned a function.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- errIllegalParametersInIter
- RegisterShardedKeyType: bad enc for %v: %v
- RegisterShardedKeyType: bad dec for %v: %v
- may only have a single context.Context parameter and it must
- may only have a single PaneInfo parameter and it must preced
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/536bbbd98bb8d130.
Report an issue: GitHub.