apache/beam · error

buildDescriptor: failed to handle coder on stage

Error message

buildDescriptor: failed to handle coder on stage %v for primary input, pcol %q %v:
%w
%v

What it means

After primary-input coder rewriting, buildDescriptor constructs the windowed value coder for the primary input via makeWindowedValueCoder. Failure means the input's coder plus window coder cannot be composed into a WindowedValue coder, so the stage cannot decode incoming elements. The error includes the stage, PCollection proto, wrapped cause, and the stage's transforms for diagnosis.

Solutions

  1. Read the wrapped %w cause for the exact failing coder
  2. Verify the PCollection's coder and windowing strategy are standard/registered
  3. Simplify windowing (e.g. global windows) to isolate the issue
  4. Upgrade to a prism runner version supporting the windowing/coder in question
Defensive patterns

Strategy: validation

Validate before calling

// Confirm windowing strategy is standard (fixed/global) before submit
ws := comps.GetWindowingStrategies()[pcol.GetWindowingStrategyId()]
if ws == nil || unsupportedWindowURN(ws) {
    return fmt.Errorf("unsupported windowing for input %q", pcolID)
}

Prevention

When it happens

Trigger: makeWindowedValueCoder(stg.primaryInput, comps, coders) errors — unknown coder IDs, missing component coders, or unsupported windowing strategies on the input PCollection.

Common situations: Non-standard windowing (custom window fns) not implemented by prism; malformed coder component chains; cross-language inputs.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

		}
		prepareSides = append(prepareSides, prepSide)
	}

	// Finally, the parallel input, which is it's own special snowflake, that needs a datasource.
	// This id is directly used for the source, but this also copies
	// coders used by side inputs to the coders map for the bundle, so
	// needs to be run for every ID.

	col := clonePColToBundle(stg.primaryInput)
	if newCID, err := lpUnknownCoders(col.GetCoderId(), coders, comps.GetCoders()); err == nil && col.GetCoderId() != newCID {
		col.CoderId = newCID
	} else if err != nil {
		return fmt.Errorf("buildDescriptor: couldn't rewrite coder %q for primary input pcollection %q: %w", col.GetCoderId(), stg.primaryInput, err)
	}

	wInCid, err := makeWindowedValueCoder(stg.primaryInput, comps, coders)
	if err != nil {
		return fmt.Errorf("buildDescriptor: failed to handle coder on stage %v for primary input, pcol %q %v:\n%w\n%v", stg.ID, stg.primaryInput, prototext.Format(col), err, stg.transforms)
	}
	ed := collectionPullDecoder(col.GetCoderId(), coders, comps)
	winCoder, wDec, wEnc := getWindowValueCoders(comps, col, coders)

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

	inputInfo := engine.PColInfo{
		GlobalID:    stg.primaryInput,
		WindowCoder: winCoder,
		WDec:        wDec,
		WEnc:        wEnc,
		EDec:        ed,
		KeyDec:      kd,
	}

View on GitHub (pinned to 12126d8942)