apache/beam · error

could not unmarshal KV coder from

Error message

could not unmarshal KV coder from %v, want exactly 2 components but have %d

What it means

When makeCoder encounters a KV coder URN, it expects exactly two component coders (key and value). If the coder proto lists a different number of components, unmarshaling fails with this error including the raw coder proto and the actual component count.

Solutions

  1. Inspect the printed coder proto in the error and ensure the KV coder declares exactly 2 component coder IDs.
  2. Fix the pipeline construction code so KV PCollections register both key and value coders.
  3. Regenerate the pipeline with a standard Beam SDK rather than hand-building coder protos.
  4. Check the producing runner/SDK for known bugs in coder serialization.
Defensive patterns

Strategy: validation

Validate before calling

if c := comps.GetCoders()[kvCoderID]; c != nil && len(c.GetComponentCoderIds()) != 2 {
    return fmt.Errorf("KV coder %s must have 2 components, has %d", kvCoderID, len(c.GetComponentCoderIds()))
}

Try / catch

cd, err := um.Coder(id)
if err != nil && strings.Contains(err.Error(), "want exactly 2 components") {
    log.Printf("malformed KV coder proto: %v", err)
}

Prevention

When it happens

Trigger: makeCoder processing beam:coders:kv:v1 with components != 2, typically from a malformed or hand-edited pipeline proto, or a runner emitting a KV coder with wrong component arity.

Common situations: Custom runners or foreign SDKs producing non-conformant KV coders; corrupted pipeline serialization; manual proto construction that forgot one KV component.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/coder.go:212

	switch urn {
	case urnBytesCoder:
		return coder.NewBytes(), nil

	case urnBoolCoder:
		return coder.NewBool(), nil

	case urnVarIntCoder:
		return coder.NewVarInt(), nil

	case urnDoubleCoder:
		return coder.NewDouble(), nil

	case urnStringCoder:
		return coder.NewString(), nil

	case urnKVCoder:
		if len(components) != 2 {
			return nil, errors.Errorf("could not unmarshal KV coder from %v, want exactly 2 components but have %d", c, len(components))
		}

		key, err := b.Coder(components[0])
		if err != nil {
			return nil, err
		}

		id := components[1]
		elm, err := b.peek(id)
		if err != nil {
			return nil, errors.Errorf("could not unmarshal kv coder value component: %w", err)
		}

		switch elm.GetSpec().GetUrn() {
		case urnIterableCoder, urnStateBackedIterableCoder:
			iterElmID := elm.GetComponentCoderIds()[0]

			// TODO(https://github.com/apache/beam/issues/18032): If CoGBK with > 1 input, handle as special GBK. We expect

View on GitHub (pinned to 12126d8942)