apache/beam · error
Invalid signature for StartBundle
Error message
Invalid signature for StartBundle
What it means
buildStartBundleWrapper counts the StartBundle method's return values via reflection; any method with 0 inputs but more than 1 output falls into the default branch and panics because StartBundle may only return 0 or 1 values (at most an error). The SDK deliberately rejects multi-return StartBundle signatures at registration time.
Source
Thrown at sdks/go/pkg/beam/register/register.go:251
startBundleOut = startBundleMethod.Type().NumOut()
switch {
case startBundleIn == 0:
switch {
case startBundleOut == 0:
if _, ok := doFn.(startBundle0x0); ok {
return registerStartBundle0x0FuncAndMakeStructWrapper()
} else {
panic("Unable to infer the types of StartBundle")
}
case startBundleOut == 1:
if _, ok := doFn.(startBundle0x1[error]); ok {
return registerStartBundle0x1FuncAndMakeStructWrapper[error]()
} else {
panic("Unable to infer the types of StartBundle")
}
default:
panic("Invalid signature for StartBundle")
}
case startBundleIn == 1:
switch {
case startBundleOut == 0:
if _, ok := doFn.(startBundle1x0[I9]); ok {
return registerStartBundle1x0FuncAndMakeStructWrapper[I9]()
} else if _, ok := doFn.(startBundle1x0[context.Context]); ok {
return registerStartBundle1x0FuncAndMakeStructWrapper[context.Context]()
} else if _, ok := doFn.(startBundle1x0[typex.PaneInfo]); ok {
return registerStartBundle1x0FuncAndMakeStructWrapper[typex.PaneInfo]()
} else if _, ok := doFn.(startBundle1x0[[]typex.Window]); ok {
return registerStartBundle1x0FuncAndMakeStructWrapper[[]typex.Window]()
} else if _, ok := doFn.(startBundle1x0[typex.EventTime]); ok {
return registerStartBundle1x0FuncAndMakeStructWrapper[typex.EventTime]()
} else if _, ok := doFn.(startBundle1x0[typex.BundleFinalization]); ok {
return registerStartBundle1x0FuncAndMakeStructWrapper[typex.BundleFinalization]()
} else {View on GitHub (pinned to 12126d8942)
Solutions
- Reduce StartBundle to at most one return value: either no returns or exactly `error`.
- Move any non-error outputs into bundle setup done in Setup() or into the DoFn's fields.
- Compare against the documented StartBundle signature options in the Beam Go programming guide.
Example fix
// before
func (fn myDoFn) StartBundle() (int, error) { return 0, nil }
// after
func (fn myDoFn) StartBundle() error { return nil } Defensive patterns
Strategy: validation
Validate before calling
m := reflect.TypeOf(myDoFn{}).MethodByName("StartBundle")
if m.IsValid && m.Type.NumOut() > 1 { panic("StartBundle must return 0 or 1 values") } Type guard
func validStartBundleArity(t reflect.Type) bool { m, ok := t.MethodByName("StartBundle"); return !ok || m.Type.NumOut() <= 1 } Try / catch
defer func() {
if r := recover(); r != nil {
log.Fatalf("invalid StartBundle signature: %v", r)
}
}() Prevention
- Remember StartBundle returns at most one error
- Do not copy ProcessElement multi-return signatures onto lifecycle methods
- Add a compile-time interface assertion var _ startBundleShape = myDoFn{}
When it happens
Trigger: Registering a DoFn whose StartBundle has 0 input parameters and 2+ return values, e.g. `func (fn myDoFn) StartBundle() (int, error)`, and passing it to beam.ParDo.
Common situations: Copy-pasting a ProcessElement-style multi-return signature onto StartBundle; accidentally adding a second return value when adding logging/state; code generators emitting ProcessElement-shaped lifecycle methods.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- panic(err)
- Unable to infer the types of StartBundle
- Invalid signature for FinishBundle
- invoker: %v has > 5 return values, which is not permitted
- OnTimer function is defined for the DoFn but no TimerProvide
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/81067257c82d1ce4.
Report an issue: GitHub.