apache/beam · error

Failed to optimize ExtractOutput for combiner %v. Failed to

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.

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)

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.