{"record":{"id":"dcb0a527b0b832cf","repo":"apache/beam","slug":"failed-to-optimize-addinput-for-combiner-v-failed-to-infer","errorCode":null,"errorMessage":"Failed to optimize AddInput for combiner %v. Failed to infer types","messagePattern":"Failed to optimize AddInput for combiner (.+?)\\. Failed to infer types","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/register/register.go","lineNumber":7955,"sourceCode":"\t\t\t\treturn fn.(addInput2x2[T0, T0]).AddInput(a0, a1)\n\t\t\t})\n\t\t}\n\t} else if _, ok := accum.(addInput2x1[T0, T0]); ok {\n\t\tcaller := func(fn any) reflectx.Func {\n\t\t\tf := fn.(func(T0, T0) T0)\n\t\t\treturn &caller2x1[T0, T0, T0]{fn: f}\n\t\t}\n\t\treflectx.RegisterFunc(reflect.TypeOf((*func(T0, T0) T0)(nil)).Elem(), caller)\n\n\t\taddInputWrapper = func(fn any) reflectx.Func {\n\t\t\treturn reflectx.MakeFunc(func(a0 T0, a1 T0) T0 {\n\t\t\t\treturn fn.(addInput2x1[T0, T0]).AddInput(a0, a1)\n\t\t\t})\n\t\t}\n\t}\n\n\tif m := accumVal.MethodByName(\"AddInput\"); m.IsValid() && addInputWrapper == nil {\n\t\tpanic(fmt.Sprintf(\"Failed to optimize AddInput for combiner %v. Failed to infer types\", accum))\n\t}\n\n\tvar extractOutputWrapper func(fn any) reflectx.Func\n\tif _, ok := accum.(extractOutput1x2[T0, T0]); ok {\n\t\tcaller := func(fn any) reflectx.Func {\n\t\t\tf := fn.(func(T0) (T0, error))\n\t\t\treturn &caller1x2[T0, T0, error]{fn: f}\n\t\t}\n\t\treflectx.RegisterFunc(reflect.TypeOf((*func(T0) (T0, error))(nil)).Elem(), caller)\n\n\t\textractOutputWrapper = func(fn any) reflectx.Func {\n\t\t\treturn reflectx.MakeFunc(func(a0 T0) (T0, error) {\n\t\t\t\treturn fn.(extractOutput1x2[T0, T0]).ExtractOutput(a0)\n\t\t\t})\n\t\t}\n\t} else if _, ok := accum.(extractOutput1x1[T0, T0]); ok {\n\t\tcaller := func(fn any) reflectx.Func {\n\t\t\tf := fn.(func(T0) T0)","sourceCodeStart":7937,"sourceCodeEnd":7973,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/register/register.go#L7937-L7973","documentation":"Panicked from register.Combiner1/Combiner2 in register.go. After failing to build a typed AddInput wrapper, the code checks reflectively whether the combiner has an AddInput method at all; if it does but the method doesn't satisfy addInput2x2[T0,T0] (AddInput(T0, T0) (T0, error)) or addInput2x1[T0,T0] (AddInput(T0, T0) T0) for the inferred types, registration panics with this message.","triggerScenarios":"register.Combiner1[T](&c{}) or Combiner2 where c.AddInput has a signature other than `(T0, T0) T0` or `(T0, T0) (T0, error)` — e.g. AddInput(accum T0, input T1) with a distinct input type while using Combiner1, extra parameters, or return type not matching T0.","commonSituations":"Using Combiner1 for a combiner whose input type differs from accumulator type (needs Combiner2); AddInput defined with a value receiver type vs pointer mismatch is not the issue here but wrong generic parameters are; hand-written CombineFn ported from Java/Python with a differently shaped AddInput.","solutions":["Make AddInput match `func (c *C) AddInput(accum T, input T) T` or `func (c *C) AddInput(accum T, input T) (T, error)` with T equal to the first type parameter.","If input type differs from accumulator type, use register.Combiner2[AccumT, InputT] instead of Combiner1.","Verify AddInput takes exactly two parameters and returns the accumulator type (optionally with error).","Drop AddInput if unused, or implement one of the register package's addInput interfaces explicitly to catch signature drift at compile time."],"exampleFix":"// before\nfunc (c *Avg) AddInput(a float64, v int) float64 { return a + float64(v) }\nregister.Combiner1[float64](&Avg{})\n\n// after\nfunc (c *Avg) AddInput(a float64, v float64) float64 { return a + v }\nregister.Combiner1[float64](&Avg{})","handlingStrategy":"validation","validationCode":"func validateAddInput[T0 any](c any) bool {\n\t_, ok1 := c.(interface{ AddInput(T0, T0) T0 })\n\t_, ok2 := c.(interface{ AddInput(T0, T0) (T0, error) })\n\treturn ok1 || ok2\n}\n// call before register.Combiner1[T0](&c{}); panic in a test if false","typeGuard":"func hasTypedAddInput[T0 any](c any) bool {\n\t_, ok1 := c.(interface{ AddInput(T0, T0) T0 })\n\t_, ok2 := c.(interface{ AddInput(T0, T0) (T0, error) })\n\treturn ok1 || ok2\n}","tryCatchPattern":null,"preventionTips":["Keep AddInput's parameter and return types identical to the accumulator type parameter.","Use Combiner2[AccumT, InputT] whenever input type differs from accumulator type.","Add compile-time assertions for the addInput interfaces your combiner intends to satisfy.","Test registration in unit tests by invoking the register call directly."],"tags":["go","apache-beam","combiner","signature-mismatch","panic"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}