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.OutView on GitHub (pinned to 12126d8942)
Solutions
- Ensure the runner window-encodes the coder for the DataSource (use graphx coders that wrap with window coders)
- Align runner and Beam Go SDK versions
- 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
- Always encode source coders through graphx window-aware coder registry
- Test cross-version runner/SDK compatibility in CI
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
- could not unmarshal window coder for pcollection %v: %w
- unwindowed coder %v on DataSink %v: %v
- could not unmarshal window coder for timer: %w
- could not unmarshal global window coder: %w
- window must not be nil
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/d711b4e44b16dbe3.
Report an issue: GitHub.