apache/beam · error · Error
Unsupported non-merging WindowFn
Error message
Unsupported non-merging WindowFn: ${windowingStrategy} What it means
CombinePerKeyPrecombineOperator.checkSupportsWindowing guards the precombine optimization: it only works when the windowing strategy's mergeStatus is NON_MERGING, but the supplied strategy requires merging windows (e.g. sessions). The windowingStrategy input is at fault — combining pre-window-merge is not implemented in this operator.
Solutions
- Use fixed or global windows instead of a merging WindowFn such as sessions.
- Fall back to a regular CombinePerKey without precombine so merging windows are handled after window merge.
- File an issue/patch to teach the precombine operator about merging window fns if you need sessions with precombine.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at sdks/typescript/src/apache_beam/worker/operators.ts:441 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/bb5c0518f261273e.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/typescript/src/apache_beam/worker/operators.ts:441
export class CombinePerKeyPrecombineOperator<I, A, O>
extends CombineOperator<I, A, O>
implements IOperator
{
keyCoder: Coder<unknown>;
windowCoder: Coder<Window>;
// Use a Map for LRU ordering: JavaScript Maps preserve insertion order,
// so we can implement LRU by deleting and re-inserting on access.
groups: Map<string, A>;
maxKeys: number = 10000;
static checkSupportsWindowing(
windowingStrategy: runnerApi.WindowingStrategy,
) {
if (
windowingStrategy.mergeStatus !== runnerApi.MergeStatus_Enum.NON_MERGING
) {
throw new Error("Unsupported non-merging WindowFn: " + windowingStrategy);
}
if (
windowingStrategy.outputTime !== runnerApi.OutputTime_Enum.END_OF_WINDOW
) {
throw new Error(
"Unsupported windowing output time: " + windowingStrategy,
);
}
}
constructor(
transformId: string,
transform: PTransform,
context: OperatorContext,
) {
super(transformId, transform, context);
const inputPc =
context.descriptor.pcollections[View on GitHub (pinned to 12126d8942)