apache/beam · error

buildDescriptor: failed to handle coder on stage

Error message

buildDescriptor: failed to handle coder on stage %v for output %+v, pcol %q %v:
%w %v

What it means

For each stage output, buildDescriptor builds the windowed value coder via makeWindowedValueCoder. Failure here means the output PCollection's coder chain (components, window coders) cannot be resolved or constructed, so elements leaving the stage cannot be encoded for downstream consumers.

Solutions

  1. Read the wrapped error and the listed stage transforms to find the unresolvable coder
  2. Ensure all custom coders are properly registered in the pipeline's components
  3. Upgrade the Beam SDK/runner pair so coder URNs match supported set
  4. Dump pipeline components (prototext) and verify coder IDs referenced by the output PCollection exist

Example fix

// before: pcol references coder id not in components
pcoll.CoderId = "customCoderId"
// after
pcoll.CoderId = beam.EncodedCoder(p, beam.NewCoder(MyType{})) // registers into components
Defensive patterns

Strategy: validation

Validate before calling

// Verify output PCollection coder chain resolves
for cid := range componentCoderIds(pcoll.GetCoderId(), comps) {
    if _, ok := comps.GetCoders()[cid]; !ok {
        return fmt.Errorf("output coder %q missing from components", cid)
    }
}

Try / catch

err := job.Submit(ctx)
if err != nil && strings.Contains(err.Error(), "failed to handle coder") {
    log.Printf("pipeline coder resolution failed: %v", err)
    return errFallbackToDirectRunner(p)
}

Prevention

When it happens

Trigger: makeWindowedValueCoder(o.Global, comps, coders) returns an error for a stage output PCollection — typically an unknown coder ID, malformed component coder list, or unsupported windowing strategy.

Common situations: Custom coders registered in the pipeline but not representable by the Go runner; cross-language output collections; pipelines built by SDK versions with coder URNs prism doesn't implement.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/runners/prism/internal/stage.go:552

			pyld, err := proto.MarshalOptions{}.Marshal(pardo)
			if err != nil {
				return fmt.Errorf("unable to encode ParDoPayload for %v in stage %v after rewrite", tid, stg.ID)
			}
			t.Spec.Payload = pyld
		}
	}
	if len(transforms) == 0 {
		return fmt.Errorf("buildDescriptor: invalid stage - no transforms at all %v", stg.ID)
	}

	// Start with outputs, since they're simple and uniform.
	sink2Col := map[string]string{}
	col2Coders := map[string]engine.PColInfo{}
	for _, o := range stg.outputs {
		col := clonePColToBundle(o.Global)
		wOutCid, err := makeWindowedValueCoder(o.Global, comps, coders)
		if err != nil {
			return fmt.Errorf("buildDescriptor: failed to handle coder on stage %v for output %+v, pcol %q %v:\n%w %v", stg.ID, o, o.Global, prototext.Format(col), err, stg.transforms)
		}
		sinkID := o.Transform + "_" + o.Local
		ed := collectionPullDecoder(col.GetCoderId(), coders, comps)

		var kd func(io.Reader) []byte
		if kcid, ok := extractKVCoderID(col.GetCoderId(), coders); ok {
			kd = collectionPullDecoder(kcid, coders, comps)
		}

		winCoder, wDec, wEnc := getWindowValueCoders(comps, col, coders)
		sink2Col[sinkID] = o.Global
		col2Coders[o.Global] = engine.PColInfo{
			GlobalID:    o.Global,
			WindowCoder: winCoder,
			WDec:        wDec,
			WEnc:        wEnc,
			EDec:        ed,
			KeyDec:      kd,

View on GitHub (pinned to 12126d8942)