apache/beam · error

Failed to optimize ExtractOutput for combiner

Error message

Failed to optimize ExtractOutput for combiner %v. Failed to infer types

What it means

Panicked from register.Combiner1/Combiner2 in register.go. The registration code tries to wrap ExtractOutput via extractOutput1x2[T0,T0] (ExtractOutput(T0) (T0, error)) or extractOutput1x1[T0,T0] (ExtractOutput(T0) T0). If the combiner exposes an ExtractOutput method (detected by MethodByName) that fits neither shape for the inferred types, no wrapper can be constructed and the library panics.

Solutions

  1. Make ExtractOutput match `func (c *C) ExtractOutput(accum T) T` or `func (c *C) ExtractOutput(accum T) (T, error)` for the type parameter used.
  2. If output type differs from accumulator type, register with Combiner2[AccumT, OutputT] and shape methods accordingly.
  3. Ensure ExtractOutput takes exactly one accumulator argument.
  4. Remove ExtractOutput if the accumulator itself is the output.

Example fix

// before
func (c *Sum) ExtractOutput(a *Stats) int { return a.total }
register.Combiner1[*Stats](&Sum{})

// after
func (c *Sum) ExtractOutput(a *Stats) (*Stats, error) { return a, nil }
register.Combiner1[*Stats](&Sum{})
Defensive patterns

Strategy: validation

Validate before calling

func validateExtractOutput[T0 any](c any) bool {
	_, ok1 := c.(interface{ ExtractOutput(T0) T0 })
	_, ok2 := c.(interface{ ExtractOutput(T0) (T0, error) })
	return ok1 || ok2
}
// verify before register.Combiner1[T0](&c{})

Type guard

func hasTypedExtractOutput[T0 any](c any) bool {
	_, ok1 := c.(interface{ ExtractOutput(T0) T0 })
	_, ok2 := c.(interface{ ExtractOutput(T0) (T0, error) })
	return ok1 || ok2
}

Prevention

When it happens

Trigger: register.Combiner1[T](&c{}) or Combiner2 where c.ExtractOutput's parameter or return type doesn't equal the inferred T0 — e.g. ExtractOutput(accum AccumT) OutputT with AccumT != OutputT under Combiner1, extra arguments, or returns types unsupported by the wrappers.

Common situations: Combiner producing a different output type than the accumulator (e.g. averaging accumulates [sum,count] and extracts a float) registered with Combiner1 instead of Combiner2; type parameter order mistakes in Combiner2; refactoring ExtractOutput to return multiple values.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/6b725ef2a13643c8. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/register/register.go:7986

				return fn.(extractOutput1x2[T0, T0]).ExtractOutput(a0)
			})
		}
	} else if _, ok := accum.(extractOutput1x1[T0, T0]); ok {
		caller := func(fn any) reflectx.Func {
			f := fn.(func(T0) T0)
			return &caller1x1[T0, T0]{fn: f}
		}
		reflectx.RegisterFunc(reflect.TypeOf((*func(T0) T0)(nil)).Elem(), caller)

		extractOutputWrapper = func(fn any) reflectx.Func {
			return reflectx.MakeFunc(func(a0 T0) T0 {
				return fn.(extractOutput1x1[T0, T0]).ExtractOutput(a0)
			})
		}
	}

	if m := accumVal.MethodByName("ExtractOutput"); m.IsValid() && extractOutputWrapper == nil {
		panic(fmt.Sprintf("Failed to optimize ExtractOutput for combiner %v. Failed to infer types", accum))
	}

	wrapperFn := func(fn any) map[string]reflectx.Func {
		m := map[string]reflectx.Func{}
		if mergeAccumulatorsWrapper != nil {
			m["MergeAccumulators"] = mergeAccumulatorsWrapper(fn)
		}
		if createAccumulatorWrapper != nil {
			m["CreateAccumulator"] = createAccumulatorWrapper(fn)
		}
		if addInputWrapper != nil {
			m["AddInput"] = addInputWrapper(fn)
		}
		if extractOutputWrapper != nil {
			m["ExtractOutput"] = extractOutputWrapper(fn)
		}

		return m

View on GitHub (pinned to 12126d8942)