apache/beam · error
Unable to infer the types of FinishBundle
Error message
Unable to infer the types of FinishBundle
What it means
In buildFinishBundleWrapper, the finishBundleIn == 0, finishBundleOut == 0 case asserts the DoFn implements finishBundle0x0 (a FinishBundle with no inputs and no outputs). If the assertion fails, the library cannot infer the types for the wrapper and panics. FinishBundle supports only a small set of signatures (optional context/EventTime/BundleFinalization inputs, nothing or error returned).
Source
Thrown at sdks/go/pkg/beam/register/register.go:1266
func buildFinishBundleWrapper[I0, I1, I2, I3, I4, I5, I6, I7, I8, I9 any](doFn any) func(any) reflectx.Func {
finishBundleIn := -1
finishBundleOut := -1
finishBundleMethod := reflect.ValueOf(doFn).MethodByName("FinishBundle")
if !finishBundleMethod.IsValid() {
return nil
}
finishBundleIn = finishBundleMethod.Type().NumIn()
finishBundleOut = finishBundleMethod.Type().NumOut()
switch {
case finishBundleIn == 0:
switch {
case finishBundleOut == 0:
if _, ok := doFn.(finishBundle0x0); ok {
return registerFinishBundle0x0FuncAndMakeStructWrapper()
} else {
panic("Unable to infer the types of FinishBundle")
}
case finishBundleOut == 1:
if _, ok := doFn.(finishBundle0x1[error]); ok {
return registerFinishBundle0x1FuncAndMakeStructWrapper[error]()
} else {
panic("Unable to infer the types of FinishBundle")
}
default:
panic("Invalid signature for FinishBundle")
}
case finishBundleIn == 1:
switch {
case finishBundleOut == 0:
if _, ok := doFn.(finishBundle1x0[I9]); ok {
return registerFinishBundle1x0FuncAndMakeStructWrapper[I9]()
} else if _, ok := doFn.(finishBundle1x0[context.Context]); ok {
return registerFinishBundle1x0FuncAndMakeStructWrapper[context.Context]()View on GitHub (pinned to 12126d8942)
Solutions
- Define FinishBundle with a pointer receiver: func (fn *myFn) FinishBundle().
- Ensure FinishBundle returns either nothing or exactly one error.
- Pass the DoFn pointer (&myFn{}) to register.DoFn so the interface assertion can match.
- Rename the method to exactly FinishBundle.
Example fix
// before
func (fn myFn) FinishBundle() bool { ... }
// after
func (fn *myFn) FinishBundle() { ... } Defensive patterns
Strategy: validation
Validate before calling
st := reflect.TypeOf(&myFn{}).Elem()
if m, ok := st.MethodByName("FinishBundle"); ok {
if m.Type.NumIn() != 1 || m.Type.NumOut() != 0 { panic("0-input FinishBundle must be func() with no returns") }
}
Type guard
func isBareFinishBundle(fn any) bool { _, ok := fn.(interface{ FinishBundle() }); return ok }
Try / catch
defer func() { if r := recover(); r != nil { err = fmt.Errorf("FinishBundle not registerable: %v", r) } }()
Prevention
- Use pointer receivers on lifecycle methods
- Pass &myFn{} to register.DoFn
- Name the method exactly FinishBundle
- Return nothing or error only
When it happens
Trigger: A DoFn whose FinishBundle takes 0 inputs but is not exactly func() — e.g. it returns a non-error value, or the method name/pointer receiver prevents the finishBundle0x0 interface assertion from succeeding.
Common situations: Defining FinishBundle with a value receiver while the assertion is done against the pointer-typed doFn; naming the method Finishbundle; giving FinishBundle an unsupported return type like (bool).
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
- Invalid signature for FinishBundle
- first main input parameter must be a value type
- ProcessElement uses a TimerProvider, but no Timer fields are
- invalid bundle processing state: %d
- panic in ElementManager.Bundles watermark evaluation gorouti
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/6230a39bf2da1c52.
Report an issue: GitHub.