apache/beam · error

could not unmarshal windowed value coder from

Error message

could not unmarshal windowed value coder from %v, expected two components but got %d

What it means

makeCoder handles both the standard and parametrized windowed-value coder URNs and expects exactly two components: the element coder and the window coder. Any other component count triggers this error naming the coder proto and the observed count.

Solutions

  1. Ensure the windowed value coder declares exactly two components: [element coder, window coder].
  2. Regenerate the pipeline proto with a standard Beam SDK instead of manual construction.
  3. Check for version skew between the SDK that produced the pipeline and the local unmarshaller.
  4. Inspect the coder proto in the message to identify which component is missing or extra.
Defensive patterns

Strategy: validation

Validate before calling

if wv := comps.GetCoders()[wvCoderID]; wv != nil && len(wv.GetComponentCoderIds()) != 2 {
    return fmt.Errorf("windowed value coder %s must have [element, window] components, has %d", wvCoderID, len(wv.GetComponentCoderIds()))
}

Try / catch

cd, err := um.Coder(id)
if err != nil && strings.Contains(err.Error(), "expected two components") {
    log.Printf("malformed windowed value coder: %v", err)
}

Prevention

When it happens

Trigger: makeCoder on beam:coders:windowed_value:v1 (or param_windowed_value) with components != 2, from malformed protos or non-conformant runners/SDKs.

Common situations: Hand-built pipeline protos missing the window component; interop with foreign SDK versions emitting different arity; corrupted pipeline serialization.

Related errors


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

Appendix: source

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

			}
			custom.ID = components[0]
			t := typex.New(custom.Type)
			cc := &coder.Coder{Kind: coder.Custom, T: t, Custom: custom}
			return cc, nil
		// case urnBytesCoder, urnStringCoder: // implicitly length prefixed types.
		//	return b.makeCoder(components[0], sub)
		default:
			// Handle Length prefixing dictated by the runner.
			cc, err := b.makeCoder(components[0], sub)
			if err != nil {
				return nil, err
			}
			return &coder.Coder{Kind: coder.LP, T: cc.T, Components: []*coder.Coder{cc}}, nil
		}

	case urnWindowedValueCoder, urnParamWindowedValueCoder:
		if len(components) != 2 {
			return nil, errors.Errorf("could not unmarshal windowed value coder from %v, expected two components but got %d", c, len(components))
		}

		elm, err := b.Coder(components[0])
		if err != nil {
			return nil, err
		}
		w, err := b.WindowCoder(components[1])
		if err != nil {
			return nil, errors.Errorf("could not unmarshal window coder: %w", err)
		}
		t := typex.New(typex.WindowedValueType, elm.T)
		wvc := &coder.Coder{Kind: coder.WindowedValue, T: t, Components: []*coder.Coder{elm}, Window: w}
		if urn == urnWindowedValueCoder {
			return wvc, nil
		}
		wvc.Kind = coder.ParamWindowedValue
		wvc.Window.Payload = string(c.GetSpec().GetPayload())
		return wvc, nil

View on GitHub (pinned to 12126d8942)