apache/beam · error

key coder for %v is %v, want %v

Error message

key coder for %v is %v, want %v

What it means

Error returned by NewCoGBK when two inputs to a CoGBK edge have different key coders: the key coder of a later input does not Equals the first input's key coder c. Even if key types agree structurally, the runner requires identical coders so keys hash/encode consistently across all joined collections.

Source

Thrown at sdks/go/pkg/beam/core/graph/edge.go:225

	}
	if !typex.IsKV(ns[0].Type()) {
		return nil, addContext(errors.Errorf("input type must be KV: %v", ns[0]), s)
	}

	// (1) Create CoGBK result type: KV<T,U>, .., KV<T,Z> -> CoGBK<T,U,..,Z>.

	c := ns[0].Coder.Components[0]
	w := inputWindow(ns)
	bounded := inputBounded(ns)
	comp := []typex.FullType{c.T, ns[0].Type().Components()[1]}

	for i := 1; i < len(ns); i++ {
		n := ns[i]
		if !typex.IsKV(n.Type()) {
			return nil, addContext(errors.Errorf("input type must be KV: %v", n), s)
		}
		if !n.Coder.Components[0].Equals(c) {
			return nil, addContext(errors.Errorf("key coder for %v is %v, want %v", n, n.Coder.Components[0], c), s)
		}
		if !w.Equals(n.WindowingStrategy()) {
			return nil, addContext(errors.Errorf("mismatched CoGBK windowing strategies: %v, want %v", n.WindowingStrategy(), w), s)
		}
		if bounded != n.Bounded() {
			return nil, addContext(errors.Errorf("unmatched CoGBK boundedness: %v, want %v", n.Bounded(), bounded), s)
		}

		comp = append(comp, n.Type().Components()[1])
	}

	t := typex.NewCoGBK(comp...)
	out := g.NewNode(t, w, bounded)

	// (2) Add CoGBK edge

	edge := g.NewEdge(s)
	edge.Op = CoGBK

View on GitHub (pinned to 12126d8942)

Solutions

  1. Ensure all inputs derive their key coders from the same default coding of the key type
  2. Remove or uniformly apply custom key coders across all CoGBK inputs
  3. Explicitly set matching coders on the key side of each input

Example fix

// before
beam.CoGroupByKey(s, a, beam.ParDo(s, customKeyedFn, b)) // custom key coder
// after
beam.CoGroupByKey(s, a, beam.ParDo(s, defaultKeyedFn, b))
Defensive patterns

Strategy: validation

Validate before calling

keyCoder := inputs[0].Coder.Components[0]
for i, c := range inputs[1:] {
    if !c.Coder.Components[0].Equals(keyCoder) {
        return fmt.Errorf("input %d key coder mismatch", i+1)
    }
}

Try / catch

if err := beam.TryCoGroupByKey(s, a, b); err != nil {
    return fmt.Errorf("CoGroupByKey key coder mismatch: %w", err)
}

Prevention

When it happens

Trigger: Inputs whose keys have the same Go type but different coders (e.g. one side uses a custom key coder variant, another the default), detected via Coder.Components[0].Equals.

Common situations: Applying a custom key coder on one PCollection but not another, or SDK version differences producing non-equal default coders for keys.

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/a1ad32e29995b7a1. Report an issue: GitHub.