apache/beam · error

could not unmarshal timer coder from

Error message

could not unmarshal timer coder from %v, expected two component but got %d

What it means

Error returned by makeCoder when decoding a timer coder URN whose component list does not have exactly two entries (element coder + window coder). The wire-format timer coder is defined as a pair; any other arity means the CoderRef from the pipeline proto is malformed or was produced by an incompatible runner/SDK version.

Solutions

  1. Ensure the timer coder lists exactly two components: [elementCoder, windowCoder]
  2. Regenerate the pipeline with a Go SDK version supporting timer coders
  3. Align SDK versions on submitter and runner
  4. Fix hand-written coder JSON to add the missing window coder component

Example fix

// before: timer coder with only 1 component
// after: {"urn":"beam:coder:timer:v1","components":[{"urn":"beam:coder:bytes:v1","components":[]},{"urn":"beam:coder:global_window:v1","components":[]}]}
Defensive patterns

Strategy: validation

Validate before calling

if ref.Urn == "beam:coder:timer:v1" && len(ref.Components) != 2 {
    return fmt.Errorf("timer coder must have exactly 2 components (element, window), got %d", len(ref.Components))
}

Prevention

When it happens

Trigger: Decoding a timer coder whose components list has other than 2 entries — malformed graph or producer/consumer coder-encoding mismatch.

Common situations: Runner/SDK version skew around timer support; hand-assembled coder JSON missing the window component; older pipelines predating timer coder support decoded by newer harness.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

		}
		c, err := DecodeCoderRef(&ref)
		if err != nil {
			return nil, errors.Wrapf(err, "could not unmarshal CoderRef from %v, failed to decode CoderRef \"%v\"", c, string(payload))
		}
		return c, nil

	case urnIterableCoder, urnStateBackedIterableCoder:
		if len(components) != 1 {
			return nil, errors.Errorf("could not unmarshal iterable coder from %v, expected one component but got %d", c, len(components))
		}
		elm, err := b.Coder(components[0])
		if err != nil {
			return nil, err
		}
		return coder.NewI(elm), nil
	case urnTimerCoder:
		if len(components) != 2 {
			return nil, errors.Errorf("could not unmarshal timer coder from %v, expected two component 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 for timer: %w", err)
		}
		return coder.NewT(elm, w), nil
	case urnRowCoder:
		var s pipepb.Schema
		if err := proto.Unmarshal(c.GetSpec().GetPayload(), &s); err != nil {
			return nil, err
		}
		t, err := schema.ToType(&s)
		if err != nil {
			return nil, err

View on GitHub (pinned to 12126d8942)