apache/beam · error

bad CoGBK

Error message

bad CoGBK: %v

What it means

EncodeCoderRef encodes CoGBK coders as a pair of (tag, stream-of-list) refs, which requires at least two component coders (the key plus at least one value collection). A CoGBK with fewer than two components cannot be represented in the Dataflow form, so encoding fails with the offending coder in the message.

Solutions

  1. Ensure the CoGBK coder includes the key component plus one component per input PCollection (>= 2 total).
  2. Use beam.CoGBK / the SDK's coder construction for multi-input transforms instead of raw coder.Coder literals.
  3. Check any custom coder provider that substitutes coders for CoGBK outputs and restore the full component list.
  4. Re-derive the coder from the transform's inputs if it was cached from a stale pipeline version.

Example fix

// before
c := &coder.Coder{Kind: coder.CoGBK, T: t, Components: []*coder.Coder{key}}
ref, err := graphx.EncodeCoderRef(c)

// after
c := &coder.Coder{Kind: coder.CoGBK, T: t, Components: []*coder.Coder{key, value1}}
ref, err := graphx.EncodeCoderRef(c)
Defensive patterns

Strategy: validation

Validate before calling

func validCoGBK(c *coder.Coder) bool {
	return c != nil && c.Kind == coder.CoGBK && len(c.Components) >= 2
}

Type guard

func isCoGBKWithInputs(c *coder.Coder, n int) bool { return c != nil && c.Kind == coder.CoGBK && len(c.Components) == n+1 }

Try / catch

ref, err := graphx.EncodeCoderRef(c)
if err != nil {
	if strings.Contains(err.Error(), "bad CoGBK") {
		return fmt.Errorf("CoGBK coder needs key + >=1 input components: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Encoding a coder.Coder of Kind coder.CoGBK with len(c.Components) < 2 — e.g. a CoGBK coder built with only a key component, or an empty component list — during pipeline graph serialization.

Common situations: Custom transforms constructing CoGBK output coders without all input collections; programmatic pipeline builders that misassemble CoGBK coders; refactors that drop components from multi-input coders.

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/aa7151a2683b78c7. Report an issue: GitHub.

Appendix: source

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

		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]
		if len(c.Components) > 2 {
			// TODO(https://github.com/apache/beam/issues/18032): don't inject union coder for CoGBK.

			union := &CoderRef{Type: cogbklistType, Components: refs[1:]}
			value = &CoderRef{Type: lengthPrefixType, Components: []*CoderRef{union}}
		}

		stream := &CoderRef{Type: streamType, Components: []*CoderRef{value}, IsStreamLike: true}
		return &CoderRef{Type: pairType, Components: []*CoderRef{refs[0], stream}, IsPairLike: true}, nil

View on GitHub (pinned to 12126d8942)