apache/flink · error · UnsupportedOperationException
The end timestamp of a processing-time window cannot become
Error message
The end timestamp of a processing-time window cannot become earlier than the current processing time by merging. Current processing time: {processingTime} window: {mergeResult} What it means
Thrown from the MergeFunction callback in TwoOutputWindowProcessOperator while a record is added to a processing-time session window. The merged window must end strictly after the current processing time; a session that would already be at/past wall clock when created is refused with UnsupportedOperationException instead of being born expired.
Source
Thrown at flink-datastream/src/main/java/org/apache/flink/datastream/impl/extension/window/operators/TwoOutputWindowProcessOperator.java:274
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: "
+ mergeResult);
}
}
triggerContext.setKey(key);
triggerContext.setWindow(mergeResult);
triggerContext.onMerge(mergedWindows);
for (W m : mergedWindows) {
triggerContext.setWindow(m);
triggerContext.clear();
WindowUtils.deleteCleanupTimer(View on GitHub (pinned to 2f3c205e92)
Solutions
- Raise the session gap above the worst-case observed per-record delay.
- Eliminate the backpressure/stall source (parallelism, per-record cost, GC tuning).
- Move to event-time sessions when wall-clock pacing is unacceptable.
- Load-test before deploying processing-time sessions.
Example fix
// before stream.process(twoOutputFn, WindowStrategy.session(Duration.ofSeconds(2), WindowStrategy.PROCESSING_TIME)); // after stream.process(twoOutputFn, WindowStrategy.session(Duration.ofMinutes(1), WindowStrategy.PROCESSING_TIME));
Defensive patterns
Strategy: validation
Validate before calling
// setup check: processing-time session gap vs worst-case record delay
if (sessionGap.toMillis() <= maxRecordDelayMs) {
throw new IllegalArgumentException(
"session gap (" + sessionGap + ") must exceed max record delay (" + maxRecordDelayMs + "ms)");
} Prevention
- Raise the session gap above measured worst-case delay before deploying
- Address backpressure and stalls instead of shrinking gaps
- Prefer event-time sessions under variable load
When it happens
Trigger: WindowStrategy.session(gap, TimeType.PROCESSING): a record delayed longer than the session gap (backpressure, slow source, GC/checkpoint stall) merges sessions into a window whose maxTimestamp is <= current processing time at merge time.
Common situations: Small gaps under load; overloaded TaskManagers; bursty catch-up sources; tests replaying pre-timestamped records slower than wall clock.
Related errors
- The end timestamp of a processing-time window cannot become
- The end timestamp of a processing-time window cannot become
- The window uses a merging assigner, but the window state is
- The end timestamp of an event-time window cannot become earl
- Window {window} is not in in-flight window set.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/e51aa09bed66dfa0.
Report an issue: GitHub.