{"record":{"id":"b492a495561cbabe","repo":"apache/beam","slug":"failed-to-optimize-createaccumulator-for-combiner-v-failed-b492a4","errorCode":null,"errorMessage":"Failed to optimize CreateAccumulator for combiner %v. Failed to infer types","messagePattern":"Failed to optimize CreateAccumulator for combiner (.+?)\\. Failed to infer types","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"sdks/go/pkg/beam/register/register.tmpl","lineNumber":363,"sourceCode":"\t\t\treturn reflectx.MakeFunc(func() (T0, error) {\n\t\t\t\treturn fn.(createAccumulator0x2[T0]).CreateAccumulator()\n\t\t\t})\n\t\t}\n    } else if _, ok := accum.(createAccumulator0x1[T0]); ok {\n        caller := func(fn any) reflectx.Func {\n            f := fn.(func() T0)\n            return &caller0x1[T0]{fn: f}\n        }\n\t\treflectx.RegisterFunc(reflect.TypeOf((*func() T0)(nil)).Elem(), caller)\n\n        createAccumulatorWrapper = func(fn any) reflectx.Func {\n\t\t\treturn reflectx.MakeFunc(func() T0 {\n\t\t\t\treturn fn.(createAccumulator0x1[T0]).CreateAccumulator()\n\t\t\t})\n\t\t}\n    }\n    if m := accumVal.MethodByName(\"CreateAccumulator\"); m.IsValid() && createAccumulatorWrapper == nil {\n        panic(fmt.Sprintf(\"Failed to optimize CreateAccumulator for combiner %v. Failed to infer types\", accum))\n    }\n\n    var addInputWrapper func(fn any) reflectx.Func\n    if _, ok := accum.(addInput2x2[T0, T0]); ok {\n        caller := func(fn any) reflectx.Func {\n            f := fn.(func(T0, T0) (T0, error))\n            return &caller2x2[T0, T0, T0, error]{fn: f}\n        }\n\t\treflectx.RegisterFunc(reflect.TypeOf((*func(T0, T0) (T0, error))(nil)).Elem(), caller)\n\n        addInputWrapper = func(fn any) reflectx.Func {\n\t\t\treturn reflectx.MakeFunc(func(a0 T0, a1 T0) (T0, error) {\n\t\t\t\treturn fn.(addInput2x2[T0, T0]).AddInput(a0, a1)\n\t\t\t})\n\t\t}\n    } else if _, ok := accum.(addInput2x1[T0, T0]); ok {\n        caller := func(fn any) reflectx.Func {\n            f := fn.(func(T0, T0) T0)","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/register/register.tmpl#L345-L381","documentation":"Raised by register.Combiner1/2/3 when the combiner value exposes a CreateAccumulator method (found via reflect.MethodByName) but the generated type assertions — createAccumulator0x2[T0] as func() (T0, error) and createAccumulator0x1[T0] as func() T0 — both failed. Beam could not build the optimized creation wrapper for the declared accumulator type T0, so it panics rather than silently using a slow path. Note the guard: it only fires when the method exists but isn't type-inferable.","triggerScenarios":"register.CombinerN[T](&MyCombiner{}) where MyCombiner.CreateAccumulator returns something other than T0 or (T0, error) — e.g. returns a different type than the supplied type parameter, takes parameters (CreateAccumulator(seed T)), returns multiple non-error values, or the accumulator type argument simply doesn't match the method's return type.","commonSituations":"Wrong generic argument order in Combiner2/Combiner3 (accumulator must be first); CreateAccumulator initialized with config/seed parameters; combining named types vs the primitive type argument (type int vs type Count int); pointer vs value receiver making the interface assertion fail.","solutions":["Make CreateAccumulator exactly func() T0 or func() (T0, error) where T0 is the accumulator type argument you passed to Combiner1/2/3.","Fix the type parameter order: register.Combiner2[AccType, InputType] — accumulator type goes first.","Remove parameters from CreateAccumulator; move initialization/seed data into struct fields set at construction.","Register with a pointer (&MyCombiner{}) if methods use pointer receivers, and match named types exactly in the generic argument.","If the signature can't conform, use the non-optimized registration path instead of Combiner1/2/3."],"exampleFix":"// before: CreateAccumulator returns wrong type vs type param\ntype CountFn struct{}\nfunc (fn *CountFn) CreateAccumulator() int { return 0 }\nregister.Combiner1[Count](...) // Count is `type Count int`\n\n// after: align types\ntype CountFn struct{}\nfunc (fn *CountFn) CreateAccumulator() Count { return Count(0) }\nregister.Combiner1[Count](&CountFn{})","handlingStrategy":"type-guard","validationCode":"// Verify CreateAccumulator shape before CombinerN registration:\nfunc createIsOptimizable[T any](accum any) bool {\n    _, ok1 := accum.(interface{ CreateAccumulator() (T, error) })\n    _, ok2 := accum.(interface{ CreateAccumulator() T })\n    return ok1 || ok2\n}","typeGuard":"func isCreateAccumulator0x1[T any](accum any) bool {\n    _, ok := accum.(interface {\n        CreateAccumulator() T\n    })\n    return ok\n}","tryCatchPattern":"func registerCombinerSafe[T any](accum any) {\n    defer func() {\n        if r := recover(); r != nil {\n            log.Fatalf(\"CreateAccumulator on %T doesn't match func() T or func() (T, error) for T=%T: %v\", accum, *new(T), r)\n        }\n    }()\n    register.Combiner1[T](accum)\n}","preventionTips":["Define CreateAccumulator as func() T or func() (T, error) with no parameters and T equal to the accumulator type argument.","Do initialization via struct fields and a constructor, not CreateAccumulator parameters.","Match named types exactly: if the accumulator is type Count int, the generic argument must be Count.","Ensure receiver kind (pointer vs value) matches how you register the combiner.","Cover every combiner with a registration unit test to catch drift after refactors."],"tags":["go","apache-beam","panics","generics","combiner"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}