apache/beam · error
value %v must be function or (ptr to) struct
Error message
value %v must be function or (ptr to) struct
What it means
Error returned by NewFn when the value passed to be treated as a DoFn/CombineFn is of an unsupported kind — not a function and not a struct or pointer-to-struct with the expected methods. The default branch of the constructor, it names the actual type, telling the user to pass a func or a (pointer to) struct implementing the DoFn/CombineFn method set.
Source
Thrown at sdks/go/pkg/beam/core/graph/fn.go:149
}
m, ok := val.Type().MethodByName(mName)
if !ok {
continue // skip: doesn't exist
}
// CAVEAT(herohde) 5/22/2017: The type val.Type.Method.Type is not
// the same as val.Method.Type: the former has the explicit receiver.
// We'll use the receiver-less version.
f, err := funcx.New(reflectx.MakeFunc(val.Method(m.Index).Interface()))
if err != nil {
return nil, errors.Wrapf(err, "method %v invalid", mName)
}
methods[mName] = f
}
return &Fn{Recv: fn, methods: methods, annotations: annotations}, nil
default:
return nil, errors.Errorf("value %v must be function or (ptr to) struct", fn)
}
}
// Signature method names.
const (
setupName = "Setup"
startBundleName = "StartBundle"
processElementName = "ProcessElement"
finishBundleName = "FinishBundle"
teardownName = "Teardown"
createInitialRestrictionName = "CreateInitialRestriction"
splitRestrictionName = "SplitRestriction"
restrictionSizeName = "RestrictionSize"
createTrackerName = "CreateTracker"
truncateRestrictionName = "TruncateRestriction"
createWatermarkEstimatorName = "CreateWatermarkEstimator"View on GitHub (pinned to 12126d8942)
Solutions
- Pass a function or a pointer to a struct: beam.ParDo(s, &myFn{}, in)
- If using a structural DoFn, take its address before passing
- Add a compile-time assertion like var _ = fn (func or *struct) in tests
Example fix
// before
beam.ParDo(s, MyFn{count: 3}, in)
// after
beam.ParDo(s, &MyFn{count: 3}, in) Defensive patterns
Strategy: validation
Validate before calling
switch v := fn.(type) {
case func(...), *struct{}:
// ok
default:
return fmt.Errorf("fn %T must be func or *struct", fn)
} Type guard
func isFnValue(fn any) bool { return reflect.ValueOf(fn).Kind() == reflect.Func || (reflect.ValueOf(fn).Kind() == reflect.Ptr && reflect.ValueOf(fn).Elem().Kind() == reflect.Struct) } Prevention
- Always pass DoFns as &MyFn{} pointers
- Never pass struct values or non-fn primitives to beam.ParDo/beam.Combine
When it happens
Trigger: Calling NewFn, NewDoFn, or NewCombineFn with a value that is neither a function nor *struct, e.g. passing a struct by value or an int/string placeholder.
Common situations: Passing a struct literal (not &struct) to beam.ParDo; using a variable whose type changed from func to struct; accidentally passing nil or an interface holding the wrong kind.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- OnTimer function is defined for the DoFn but no TimerProvide
- OnTimer and ProcessElement functions for DoFn should have ex
- OnTimer and ProcessElement functions for DoFn should have ex
- error writing state: %v
- invalid DoFn
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/ce136f6a71d1105e.
Report an issue: GitHub.