apache/beam · error
bad parameter type for %s: %v
Error message
bad parameter type for %s: %v
What it means
funcx.New validates each parameter of a user function against known kinds (context, event time, emitters, iterators, multi-maps, etc.). When the parameter is a func type that looks like an emitter but is structurally illegal (unfoldEmit fails — e.g. emits interface{} or has a non-concrete parameter), IsMalformedEmit returns true and the wrapped error is raised as "bad parameter type for <fnName>: <type>".
Source
Thrown at sdks/go/pkg/beam/core/funcx/fn.go:434
kind = FnRTracker
case t.Implements(reflect.TypeOf((*sdf.WatermarkEstimator)(nil)).Elem()):
kind = FnWatermarkEstimator
case typex.IsContainer(t), typex.IsConcrete(t), typex.IsUniversal(t):
kind = FnValue
case IsEmit(t):
kind = FnEmit
case IsIter(t):
kind = FnIter
case IsReIter(t):
kind = FnReIter
case IsMultiMap(t):
kind = FnMultiMap
case t == typex.PaneInfoType:
kind = FnPane
default:
// Error cases
if ok, err := IsMalformedEmit(t); ok {
return nil, errors.Wrapf(err, "bad parameter type for %s: %v", fn.Name(), t)
}
if ok, err := IsMalformedIter(t); ok {
return nil, errors.Wrapf(err, "bad parameter type for %s: %v", fn.Name(), t)
}
if ok, err := IsMalformedReIter(t); ok {
return nil, errors.Wrapf(err, "bad parameter type for %s: %v", fn.Name(), t)
}
if ok, err := IsMalformedMultiMap(t); ok {
return nil, errors.Wrapf(err, "bad parameter type for %s: %v", fn.Name(), t)
}
return nil, errors.Errorf("bad parameter type for %s: %v", fn.Name(), t)
}
param = append(param, FnParam{Kind: kind, T: t})
}
var ret []ReturnParam
for i := 0; i < fn.Type().NumOut(); i++ {View on GitHub (pinned to 12126d8942)
Solutions
- Read the wrapped cause: it names the illegal parameter (e.g. "Type interface{} isn't a supported PCollection type" or errIllegalParametersInEmit).
- Make emitted element types concrete and JSON-codable (exported struct, basic type, or typex-registered type).
- Reduce emitter arity to at most 2 params: optional typex.EventTime first, then 1–2 concrete element types.
- Remove return values from emit funcs — emitters must have no outputs (NumOut == 0).
- Replace interface{} / any parameters with a concrete type or a typex universal/container type.
Example fix
// before
func (f *MyFn) ProcessElement(e string, emit func(int, string, bool)) { ... } // 3 params: malformed emit
// after
func (f *MyFn) ProcessElement(e string, emit func(MyResult)) { ... } // 1 concrete element type Defensive patterns
Strategy: validation
Validate before calling
if ok, err := funcx.IsMalformedEmit(reflect.TypeOf(emitFn)); ok {
return fmt.Errorf("emit signature rejected: %w", err)
} Type guard
func isValidEmit(t reflect.Type) bool {
ok, err := funcx.IsMalformedEmit(t)
return ok == false && err == nil && funcx.IsEmit(t)
} Try / catch
fn, err := funcx.New(reflect.ValueOf(processFn))
if err != nil {
return fmt.Errorf("DoFn %T rejected: %w", processFn, err)
} Prevention
- Emitters: no return values, at most optional typex.EventTime + 1–2 concrete params.
- Never emit interface{} or unexported types.
- Validate DoFn signatures with funcx.New in unit tests.
- Follow the documented DoFn signature patterns before adding extra parameters.
When it happens
Trigger: Binding a DoFn/CombineFn/DoFn process method whose parameter is a func(...) with return values, or an emitter whose element type is interface{} / a non-concrete type, or an emitter taking more than 2 parameters (beyond the optional EventTime).
Common situations: Writing emit funcs with wrong arity (func(T, U, V) instead of max T plus EventTime), emitting interface{} or unexported types, copying a signature that returns a value, typo in typex.EventTime placement.
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
- GBK/CoGBK result values must be iterable: %v
- Invalid signature for FinishBundle
- first main input parameter must be a value type
- ProcessElement uses a TimerProvider, but no Timer fields are
- not a function: %v
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/14fd832c0ec7f225.
Report an issue: GitHub.