apache/beam · error

unexpected inject coder

Error message

unexpected inject coder: %v

What it means

The URNInject transform moves elements into a CoGBK-style output and requires the incoming PCollection's coder to be KV so the value coder can be separated for the Inject encoder. A non-KV coder here is an internal inconsistency in the translated coder graph and triggers this error.

Solutions

  1. Keep SDK and runner on matching versions and resubmit the job
  2. Inspect the coder payload for the injected PCollection to confirm it is KV; fix the custom coder's Encode/Decode or CreateCoder so structure is preserved
  3. If an unexpected LP wrapper is involved, note it is stripped automatically — check whether a custom coder wraps values redundantly

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

c, _, err := b.makeCoderForPCollection(from)
if err != nil {
	return err
}
if !coder.IsKV(c) {
	return fmt.Errorf("inject input must be KV-coded, got %v", c)
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Coder for the 'from' PCollection of a Inject transform (used by beam.Flatten/CoGBK injection) decodes as non-KV — typically after coder payload corruption, custom coder fallback, or version-skewed coder inference between SDK and runner.

Common situations: Custom coders that change KV structure; pipelines crossing SDK version upgrades (BEAM-12438-adjacent LP coder handling); runners rewriting coder payloads.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/exec/translate.go:712

				case urnPerKeyCombineConvert:
					u = &ConvertToAccumulators{Combine: cn}
				default: // For unlifted combines
					u = cn
				}
			default:
				panic(fmt.Sprintf("Opcode should be one of ParDo or Combine, but it is: %v", op))
			}

		case graphx.URNIterableSideInputKey:
			u = &FixedKey{UID: b.idgen.New(), Key: []byte(iterableSideInputKey), Out: out[0]}

		case graphx.URNInject:
			c, _, err := b.makeCoderForPCollection(from)
			if err != nil {
				return nil, err
			}
			if !coder.IsKV(c) {
				return nil, errors.Errorf("unexpected inject coder: %v", c)
			}
			valCoder := c.Components[1]
			// JIRA BEAM-12438 - an extra LP coder can get added here, but isn't added
			// on decode. Strip them until we get a better fix.
			if valCoder.Kind == coder.LP {
				// strip unexpected length prefix coder.
				valCoder = valCoder.Components[0]
			}
			u = &Inject{UID: b.idgen.New(), N: (int)(tp.GetInject().GetN()), ValueEncoder: MakeElementEncoder(valCoder), Out: out[0]}

		case graphx.URNExpand:
			var pid string
			for _, id := range transform.GetOutputs() {
				pid = id
			}
			c, _, err := b.makeCoderForPCollection(pid)
			if err != nil {
				return nil, err

View on GitHub (pinned to 12126d8942)