apache/flink · error · UnsupportedOperationException

The end timestamp of an event-time window cannot become earl

Error message

The end timestamp of an event-time window cannot become earlier than the current watermark by merging. Current event time: {eventTime} window: {mergeResult}

What it means

Thrown from the MergeFunction callback in TwoOutputWindowProcessOperator while a record is added to an event-time session window. The merge result must still be valid at the current watermark: mergeResult.maxTimestamp() + allowedLateness must exceed the watermark, otherwise the merged session would already be expired and the merge is refused with UnsupportedOperationException. The message carries the watermark and the offending mergeResult window.

Source

Thrown at flink-datastream/src/main/java/org/apache/flink/datastream/impl/extension/window/operators/TwoOutputWindowProcessOperator.java:261

                // is the merged window and we work with that. If we don't merge then
                // actualWindow == window
                W actualWindow =
                        mergingWindows.addWindow(
                                window,
                                new MergingWindowSet.MergeFunction<>() {
                                    @Override
                                    public void merge(
                                            W mergeResult,
                                            Collection<W> mergedWindows,
                                            W stateWindowResult,
                                            Collection<W> mergedStateWindows)
                                            throws Exception {

                                        if ((windowAssigner.isEventTime()
                                                && mergeResult.maxTimestamp() + allowedLateness
                                                        <= internalTimerService
                                                                .currentWatermark())) {
                                            throw new UnsupportedOperationException(
                                                    "The end timestamp of an "
                                                            + "event-time window cannot become earlier than the current watermark "
                                                            + "by merging. Current event time: "
                                                            + internalTimerService
                                                                    .currentWatermark()
                                                            + " window: "
                                                            + mergeResult);
                                        } else if (!windowAssigner.isEventTime()) {
                                            long currentProcessingTime =
                                                    internalTimerService.currentProcessingTime();
                                            if (mergeResult.maxTimestamp()
                                                    <= currentProcessingTime) {
                                                throw new UnsupportedOperationException(
                                                        "The end timestamp of a "
                                                                + "processing-time window cannot become earlier than the current processing time "
                                                                + "by merging. Current processing time: "
                                                                + currentProcessingTime
                                                                + " window: "

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Bound out-of-orderness generously: watermark delay >= max event delay + session gap.
  2. Intercept late records upstream (compare timestamp to currentWatermark()) and route them to a side output before the two-output window operator.
  3. Use tumbling/sliding with explicit allowedLateness when merging is unnecessary.
  4. Track watermark lag metrics to size the delay budget from measured data.

Example fix

// before
WatermarkStrategy.<Event>forMonotonousTimestamps();
stream.process(twoOutputFn, WindowStrategy.session(Duration.ofMinutes(10)));
// after
WatermarkStrategy.<Event>forBoundedOutOfOrderness(Duration.ofMinutes(15));
stream.process(twoOutputFn, WindowStrategy.session(Duration.ofMinutes(10)));
Defensive patterns

Strategy: validation

Validate before calling

// keep would-be-expired merges away from the two-output window operator
long wm = ctx.currentWatermark();
if (event.timestamp() + sessionGapMs + maxDelayMs <= wm) {
    ctx.output(LATE_TAG, event);
    return;
}

Prevention

When it happens

Trigger: An out-of-order record for an event-time session window (WindowStrategy.session(gap, TimeType.EVENT)) merges sessions into a window whose end plus lateness is at/before the watermark; since session strategies default to no lateness, any merge result that expires at the current watermark throws.

Common situations: Watermark out-of-orderness smaller than real delay on the feeding stream; late side-output logic missing; replays/backfills after watermarks advanced; small session gaps amplifying sensitivity to skew.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/deb6f071cb7e362e. Report an issue: GitHub.