apache/beam · error

unwindowed coder %v on DataSource %v: %v

Error message

unwindowed coder %v on DataSource %v: %v

What it means

The DataSource node requires a windowed coder so elements carry window information. After resolving the coder from the plan's coder registry, UnmarshalPlan checks coder.IsW; if the coder is not windowed, plan construction fails with this error naming the coder id and transform.

Source

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

		if transform.GetSpec().GetUrn() != urnDataSource {
			continue
		}
		if len(transform.GetOutputs()) != 1 {
			return nil, errors.Errorf("expected one output from DataSource, got %v", transform.GetOutputs())
		}

		port, cid, err := unmarshalPort(transform.GetSpec().GetPayload())
		if err != nil {
			return nil, err
		}

		u := &DataSource{UID: b.idgen.New()}
		u.Coder, err = b.coders.Coder(cid) // Expected to be windowed coder
		if err != nil {
			return nil, err
		}
		if !coder.IsW(u.Coder) {
			return nil, errors.Errorf("unwindowed coder %v on DataSource %v: %v", cid, id, u.Coder)
		}

		// There's only a single pair in this map, but a for loop range statement
		// is the easiest way to extract it, so this loop will iterate only once.
		for key, pid := range transform.GetOutputs() {
			u.SID = StreamID{PtransformID: id, Port: port}
			u.Name = key

			u.Out, err = b.makePCollection(pid)
			if err != nil {
				return nil, err
			}
			// Elide the PCollection Node for DataSources
			// DataSources can get byte samples directly, and can handle CoGBKs.
			// Copying the PCollection here is fine, as the PCollection will never
			// have used it's mutex yet.
			u.PCol = *u.Out.(*PCollection)
			u.Out = u.PCol.Out

View on GitHub (pinned to 12126d8942)

Solutions

  1. Ensure the runner window-encodes the coder for the DataSource (use graphx coders that wrap with window coders)
  2. Align runner and Beam Go SDK versions
  3. Check that custom coder registration isn't stripping the window coder wrapper
Defensive patterns

Strategy: validation

Validate before calling

// Check coder is windowed before submitting pipeline
c, _ := coders.Coder(cid)
if c != nil && !coder.IsW(c) {
    return fmt.Errorf("coder %s must be windowed for source", cid)
}

Type guard

func isWindowed(c *coder.Coder) bool { return c != nil && coder.IsW(c) }

Try / catch

if err := unmarshalPlan(desc); err != nil {
    if strings.Contains(err.Error(), "unwindowed coder") {
        // re-encode source coder with window wrapper and retry
    }
}

Prevention

When it happens

Trigger: Runner sends a DataSource whose payload references a non-windowed coder id, during UnmarshalPlan/getOrCreatePlan.

Common situations: Runner/SDK protocol mismatch where the runner encodes raw coders without window wrapping; custom coder registration that bypasses windowing; older runners incompatible with the Go SDK's windowed-coder expectations.

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