apache/beam · error

unexpected URN for window coder

Error message

unexpected URN %v for window coder

What it means

urnToWindowCoder maps a window coder's URN to a concrete window coder, supporting only urnGlobalWindow (beam:window:global_windows) and urnIntervalWindow (beam:window:interval_windows). Any other URN produces this error with context 'translate URN to window coder'.

Solutions

  1. Use only GlobalWindows or Fixed/Interval Windows, or upgrade the Beam Go SDK to a version supporting the URN.
  2. Check for SDK version skew between pipeline submission and the runner; align versions.
  3. If custom windows are required, verify the SDK/runner actually supports that window URN before using it.
  4. Validate hand-written proto URNs against the constants in graphx (urnGlobalWindow, urnIntervalWindow).
Defensive patterns

Strategy: validation

Validate before calling

urn := wc.GetSpec().GetUrn()
if urn != "beam:window:global_windows:v1" && urn != "beam:window:interval_windows:v1" {
    return fmt.Errorf("unsupported window coder URN %q", urn)
}

Try / catch

w, err := um.WindowCoder(id)
if err != nil && strings.Contains(err.Error(), "unexpected URN") {
    log.Printf("upgrade SDK or use global/interval windows: %v", err)
}

Prevention

When it happens

Trigger: Unmarshaling a pipeline whose PCollection declares a window coder with an unrecognized URN — e.g. custom window URNs, session/test windows, or URNs from a newer SDK the local version doesn't know.

Common situations: Running a pipeline built with custom windowing against a runner/SDK that lacks that window coder support; version skew where the newer SDK emits a URN the older stager doesn't recognize; hand-written pipeline protos with typo'd URNs.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/coder.go:185

		return nil, errors.Errorf("could not unmarshal window coder: %w", err)
	}

	w, err := urnToWindowCoder(c.GetSpec().GetUrn())
	if err != nil {
		return nil, errors.SetTopLevelMsgf(err, "failed to unmarshal window coder %v", id)
	}
	b.windowCoders[id] = w
	return w, nil
}

func urnToWindowCoder(urn string) (*coder.WindowCoder, error) {
	switch urn {
	case urnGlobalWindow:
		return coder.NewGlobalWindow(), nil
	case urnIntervalWindow:
		return coder.NewIntervalWindow(), nil
	default:
		err := errors.Errorf("unexpected URN %v for window coder", urn)
		return nil, errors.WithContext(err, "translate URN to window coder")
	}
}

func (b *CoderUnmarshaller) makeCoder(id string, c *pipepb.Coder) (*coder.Coder, error) {
	urn := c.GetSpec().GetUrn()
	components := c.GetComponentCoderIds()

	switch urn {
	case urnBytesCoder:
		return coder.NewBytes(), nil

	case urnBoolCoder:
		return coder.NewBool(), nil

	case urnVarIntCoder:
		return coder.NewVarInt(), nil

View on GitHub (pinned to 12126d8942)