apache/beam · error

ExecuteTransform[GBK] stage %v, transform %q %v: couldn't pr

Error message

ExecuteTransform[GBK] stage %v, transform %q %v: couldn't process key coder:
%w

What it means

After resolving the window coder, ExecuteTransform for GBK resolves the KV's key component coder (component 0) with lpUnknownCoders. Failure there triggers this panic, naming the stage, transform, and the wrapped cause. It indicates the key coder of the GBK input KV coder could not be processed/expanded by the runner.

Source

Thrown at sdks/go/pkg/beam/runners/prism/internal/handlerunner.go:436

	switch urn {
	case urns.TransformFlatten:
		// Already done and collated.
		data = inputData

	case urns.TransformGBK:
		ws := windowingStrategy(comps, tid)
		kvc := onlyInputCoderForTransform(comps, tid)

		coders := map[string]*pipepb.Coder{}

		// TODO assert this is a KV. It's probably fine, but we should fail anyway.
		wcID, err := lpUnknownCoders(ws.GetWindowCoderId(), coders, comps.GetCoders())
		if err != nil {
			panic(fmt.Errorf("ExecuteTransform[GBK] stage %v, transform %q %v: couldn't process window coder:\n%w", stageID, tid, prototext.Format(t), err))
		}
		kcID, err := lpUnknownCoders(kvc.GetComponentCoderIds()[0], coders, comps.GetCoders())
		if err != nil {
			panic(fmt.Errorf("ExecuteTransform[GBK] stage %v, transform %q %v: couldn't process key coder:\n%w", stageID, tid, prototext.Format(t), err))
		}
		ecID, err := lpUnknownCoders(kvc.GetComponentCoderIds()[1], coders, comps.GetCoders())
		if err != nil {
			panic(fmt.Errorf("ExecuteTransform[GBK] stage %v, transform %q %v: couldn't process value coder:\n%w", stageID, tid, prototext.Format(t), err))
		}
		reconcileCoders(coders, comps.GetCoders())

		wc := coders[wcID]
		kc := coders[kcID]
		ec := coders[ecID]

		data = append(data, gbkBytes(ws, wc, kc, ec, inputData, coders))
		if len(data[0]) == 0 {
			panic("no data for GBK")
		}
	default:
		panic(fmt.Sprintf("unimplemented runner transform[%v]", urn))
	}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Inspect the wrapped error for the failing key coder ID or URN.
  2. Ensure the key coder (and any nested coders) are fully specified in the pipeline components.
  3. Update the SDK/prism versions so unsupported coder URNs are handled.
Defensive patterns

Strategy: validation

Validate before calling

// Check the GBK KV's key component coder resolves
kvc := codersByID[gbkInputCoderID]
if kvc.GetComponentCoderIds() == nil || len(kvc.GetComponentCoderIds()) < 2 {
    log.Fatalf("GBK input coder is not a KV: %q", gbkInputCoderID)
}

Try / catch

defer func() {
    if r := recover(); r != nil && strings.Contains(fmt.Sprint(r), "couldn't process key coder") {
        log.Fatalf("GBK key coder unresolved: %v", r)
    }
}()

Prevention

When it happens

Trigger: A GBK whose KV coder's componentCoderIds[0] refers to a coder that is missing, circular, or of an unsupported URN when resolved against the pipeline's coder components.

Common situations: Custom key types with coders not serialized into the pipeline; cross-language key coder mismatches; older SDK emitting coder references prism cannot expand.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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