apache/beam · error

Iterable coder must have only one component

Error message

Iterable coder must have only one component: %s

What it means

The Iterable coder must wrap exactly one component coder. prism's recursive pullDecoderNoAlloc enforces this invariant and panics when an beam:coder:iterable:v1 coder has zero or multiple component coder IDs.

Solutions

  1. Correct the Iterable coder to declare exactly one component coder ID
  2. Regenerate the pipeline with a matching Beam SDK version
  3. Inspect the prototext coder dump in the panic message to find the bad component list
  4. Check custom coder construction code that assembles Iterable coders

Example fix

// before
&pipepb.Coder{Spec: iterableUrn, ComponentCoderIds: []string{"c0", "c1"}},
// after
&pipepb.Coder{Spec: iterableUrn, ComponentCoderIds: []string{"c0"}},
Defensive patterns

Strategy: validation

Validate before calling

if c.GetSpec().GetUrn() == "beam:coder:iterable:v1" && len(c.GetComponentCoderIds()) != 1 {
    return fmt.Errorf("invalid iterable coder: %v", c)
}

Try / catch

defer func() {
    if r := recover(); r != nil && strings.Contains(fmt.Sprint(r), "Iterable coder must have only one component") {
        err = fmt.Errorf("malformed iterable coder in pipeline: %v", r)
    }
}()

Prevention

When it happens

Trigger: A submitted pipeline contains an Iterable coder whose GetComponentCoderIds length is not 1; the panic occurs while prism materializes decoders for the affected PCollection.

Common situations: Malformed graphs from SDK/runner version mismatches, custom coders built by hand, or third-party pipeline generators writing invalid component lists.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/runners/prism/internal/coders.go:339

			}
			ed(r)
		}
	case urns.CoderVarInt:
		return func(r io.Reader) {
			coder.DecodeVarInt(r)
		}
	case urns.CoderBool:
		return func(r io.Reader) {
			coder.DecodeBool(r)
		}
	case urns.CoderDouble:
		return func(r io.Reader) {
			coder.DecodeDouble(r)
		}
	case urns.CoderIterable:
		ccids := c.GetComponentCoderIds()
		if len(ccids) != 1 {
			panic(fmt.Sprintf("Iterable coder must have only one component: %s", prototext.Format(c)))
		}
		ed := pullDecoderNoAlloc(coders[ccids[0]], coders)
		return func(r io.Reader) {
			l, _ := coder.DecodeInt32(r)
			for i := int32(0); i < l; i++ {
				ed(r)
			}
		}
	case urns.CoderKV:
		ccids := c.GetComponentCoderIds()
		if len(ccids) != 2 {
			panic(fmt.Sprintf("KV coder with more than 2 components: %s", prototext.Format(c)))
		}
		kd := pullDecoderNoAlloc(coders[ccids[0]], coders)
		vd := pullDecoderNoAlloc(coders[ccids[1]], coders)
		return func(r io.Reader) {
			kd(r)
			vd(r)

View on GitHub (pinned to 12126d8942)