apache/beam · error

DoFns that observe windows must be invoked with single…

Error message

DoFns that observe windows must be invoked with single window: %v

What it means

When a DoFn declares a window parameter (n.wndIdx >= 0), invokeWithOpts requires the element to carry exactly one window, since Beam Go cannot pick a representative window for a multi-window element. If len(ws) != 1, this error is returned instead of invoking the DoFn.

Solutions

  1. Ensure elements are exploded to single windows before reaching window-observing DoFns (use ExplodeWindows semantics appropriately)
  2. Check whether the DoFn genuinely needs the window parameter; remove it if not
  3. Verify upstream windowing/merging logic (sliding/overlapping windows) is intended
  4. Report to Beam if a stock transform produces multi-window elements here (possible bug)

Example fix

// before
func (fn *myFn) ProcessElement(ctx context.Context, w beam.Window, v string) { ... }
// used with overlapping windows producing multi-window elements
// after
func (fn *myFn) ProcessElement(ctx context.Context, v string) { ... } // drop window param
// or explode elements so each invocation sees exactly one window
Defensive patterns

Strategy: validation

Validate before calling

// before invoking a window-observing DoFn, assert single-window
func hasSingleWindow(ws []beam.Window) bool { return len(ws) == 1 }

Type guard

func singleWindowOnly(ws []beam.Window) (beam.Window, bool) {
    if len(ws) != 1 { return nil, false }
    return ws[0], true
}

Try / catch

// on the runner side, catch this invocation failure
if err != nil && strings.Contains(err.Error(), "must be invoked with single window") {
    return fmt.Errorf("explode windows before this DoFn: %w", err)
}

Prevention

When it happens

Trigger: A DoFn signature includes a beam window parameter, and invokeWithOpts receives opts whose opts.opt.Key.Windows has length 0 or >1 — e.g. an element in multiple windows, or an empty window slice from a bad source.

Common situations: Elements fired into multiple overlapping windows while the DoFn observes windows; custom sources producing empty window slices; SDK-internal bug where window merging yields multi-window elements at invocation time.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/exec/fn.go:221

	return n.invokeWithOpts(ctx, pn, ws, ts, InvokeOpts{opt: opt, bf: bf, we: we, sa: sa, sr: sr, extra: extra})
}

func (n *invoker) invokeWithOpts(ctx context.Context, pn typex.PaneInfo, ws []typex.Window, ts typex.EventTime, opts InvokeOpts) (*FullValue, error) {
	// (1) Populate contexts
	// extract these to make things easier to read.
	args := n.args
	fn := n.fn
	in := n.in

	if n.ctxIdx >= 0 {
		args[n.ctxIdx] = ctx
	}
	if n.pnIdx >= 0 {
		args[n.pnIdx] = pn
	}
	if n.wndIdx >= 0 {
		if len(ws) != 1 {
			return nil, errors.Errorf("DoFns that observe windows must be invoked with single window: %v", opts.opt.Key.Windows)
		}
		args[n.wndIdx] = ws[0]
	}
	if n.etIdx >= 0 {
		args[n.etIdx] = ts
	}
	if n.bfIdx >= 0 {
		args[n.bfIdx] = opts.bf
	}
	if n.weIdx >= 0 {
		args[n.weIdx] = opts.we
	}

	if n.spIdx >= 0 {
		sp, err := opts.sa.NewStateProvider(ctx, opts.sr, ws[0], opts.opt)
		if err != nil {
			return nil, err
		}

View on GitHub (pinned to 12126d8942)