apache/beam · error

bad I

Error message

bad I: %v

What it means

EncodeCoderRef serializes a coder into the runner (Dataflow) representation. A coder.Iterable must wrap exactly one component coder (the element coder); any other component count is structurally invalid, so encoding aborts with this error naming the coder. This prevents emitting a stream CoderRef the service cannot interpret.

Solutions

  1. Ensure the Iterable coder has exactly one component: len(c.Components) == 1.
  2. Create iterable coders through the SDK (e.g. coder.NewI, or coders inferred from typex.Stream types) rather than by hand.
  3. Inspect the PCollection whose coder triggers this and fix the custom coder override.
  4. Align SDK versions if the coder was produced by decode of an older/newer pipeline artifact.

Example fix

// before
c := &coder.Coder{Kind: coder.Iterable, T: t, Components: nil}
ref, err := graphx.EncodeCoderRef(c)

// after
elem := graphx.InferCoder(typex.New(typex.StringType))
c := &coder.Coder{Kind: coder.Iterable, T: typex.New(typex.StreamType, elem.T), Components: []*coder.Coder{elem}}
ref, err := graphx.EncodeCoderRef(c)
Defensive patterns

Strategy: validation

Validate before calling

func validIterable(c *coder.Coder) bool {
	return c != nil && c.Kind == coder.Iterable && len(c.Components) == 1
}

Type guard

func hasComponents(c *coder.Coder, n int) bool { return c != nil && len(c.Components) == n }

Try / catch

ref, err := graphx.EncodeCoderRef(c)
if err != nil {
	if strings.Contains(err.Error(), "bad I") {
		return fmt.Errorf("iterable coder must have exactly 1 element component: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Encoding a coder.Coder with Kind coder.Iterable whose Components slice is empty or has more than one entry — typically via EncodeCoder/EncodeCoderRefs during pipeline submission to Dataflow.

Common situations: Manually constructed iterable coders with no element component; a GBK/PCollection transform whose output coder was overwritten with a wrong shape; version skew between the pipeline-graph serializer and a custom coder factory.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/dataflow.go:135

		value, err := EncodeCoderRef(c.Components[1])
		if err != nil {
			return nil, err
		}
		return &CoderRef{Type: pairType, Components: []*CoderRef{key, value}, IsPairLike: true}, nil

	case coder.Nullable:
		if len(c.Components) != 1 {
			return nil, errors.Errorf("bad N: %v", c)
		}
		innerref, err := EncodeCoderRef(c.Components[0])
		if err != nil {
			return nil, err
		}
		return &CoderRef{Type: nullableType, Components: []*CoderRef{innerref}}, nil

	case coder.Iterable:
		if len(c.Components) != 1 {
			return nil, errors.Errorf("bad I: %v", c)
		}
		innerref, err := EncodeCoderRef(c.Components[0])
		if err != nil {
			return nil, err
		}
		return &CoderRef{Type: streamType, Components: []*CoderRef{innerref}}, nil

	case coder.CoGBK:
		if len(c.Components) < 2 {
			return nil, errors.Errorf("bad CoGBK: %v", c)
		}

		refs, err := EncodeCoderRefs(c.Components)
		if err != nil {
			return nil, err
		}

		value := refs[1]

View on GitHub (pinned to 12126d8942)