apache/beam · error

tried to merge non-interval window type %T

Error message

tried to merge non-interval window type %T

What it means

The direct runner's CoGBK transform merges windows by grouping together windows that overlap. Windows in the incoming group are asserted to be `window.IntervalWindow` implementations; if any window is a different type (a custom WindowFn producing non-interval windows), mergeWindows returns this error since the direct runner only supports interval-window merging in this path.

Source

Thrown at sdks/go/pkg/beam/runners/direct/gbk.go:135

			return err
		}
		delete(n.m, key)
	}
	return n.Out.FinishBundle(ctx)
}

func (n *CoGBK) mergeWindows() (map[typex.Window]int, error) {
	sort.Slice(n.wins, func(i int, j int) bool {
		return n.wins[i].MaxTimestamp() < n.wins[j].MaxTimestamp()
	})
	// mergeMap is a map from the oringal windows to the index of the new window
	// in the mergedWins slice
	mergeMap := make(map[typex.Window]int)
	var mergedWins []typex.Window
	for i := 0; i < len(n.wins); {
		intWin, ok := n.wins[i].(window.IntervalWindow)
		if !ok {
			return nil, errors.Errorf("tried to merge non-interval window type %T", n.wins[i])
		}
		mergeStart := intWin.Start
		mergeEnd := intWin.End
		j := i + 1
		for j < len(n.wins) {
			candidateWin := n.wins[j].(window.IntervalWindow)
			if candidateWin.Start <= mergeEnd {
				mergeEnd = candidateWin.End
				j++
			} else {
				break
			}
		}
		for k := i; k < j; k++ {
			mergeMap[n.wins[k]] = len(mergedWins)
		}
		mergedWins = append(mergedWins, window.IntervalWindow{Start: mergeStart, End: mergeEnd})
		i = j

View on GitHub (pinned to 12126d8942)

Solutions

  1. Use a standard interval-based windowing function (window.FixedWindows, window.SlidingWindows, window.Sessions) instead of a custom non-interval WindowFn.
  2. Make the custom WindowFn assign windows that implement the window.IntervalWindow interface (with Start/End methods).
  3. Run the pipeline with a different runner that supports the custom window type.

Example fix

// before: custom non-interval window
type GlobalOnlyWindow struct{}
func (GlobalOnlyWindow) AssignWindows(...) { ... }
// after: interval-based window
w := window.NewFixedWindows(60 * time.Second)
pcoll := beam.WindowInto(s, w, pcoll)
Defensive patterns

Strategy: validation

Validate before calling

// Go: assert your windowing assigns IntervalWindows before the GBK stage
if _, ok := windowing.(interface{ IntervalWindow }) ; !ok { /* switch to FixedWindows/SlidingWindows/Sessions */ }

Type guard

func isIntervalWindow(w typex.Window) bool { _, ok := w.(window.IntervalWindow); return ok }

Prevention

When it happens

Trigger: A pipeline using a custom WindowFn (or a built-in one) whose windows do not implement window.IntervalWindow is executed with the direct runner on a CoGBK/group-by-key stage. The error occurs in mergeWindows when type-asserting n.wins[i] to IntervalWindow fails.

Common situations: Developers implementing custom windowing functions and running pipelines with the direct runner; switching runners where a windowing scheme supported elsewhere is not supported by the direct GBK merge path.

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