apache/flink · critical · IllegalStateException
The window uses a merging assigner, but the window state is
Error message
The window uses a merging assigner, but the window state is not mergeable.
What it means
Sanity check during TwoOutputWindowProcessOperator initialization (windows with a main and side output). When the assigner is a MergingWindowAssigner (session windows), the per-window state must implement InternalMergingState to merge contents of merged-away windows; a non-null windowState that fails the instanceof check makes open() throw IllegalStateException, so the job fails to start. Standard backends (hashmap, RocksDB/ForSt) satisfy this, pointing to a custom backend or state registration as the cause.
Source
Thrown at flink-datastream/src/main/java/org/apache/flink/datastream/impl/extension/window/operators/TwoOutputWindowProcessOperator.java:175
// NOTE - the state may be null in the case of the overriding evicting window operator
if (windowStateDescriptor != null) {
windowState =
getOrCreateKeyedState(
windowSerializer.createInstance(),
windowSerializer,
windowStateDescriptor);
}
// create the typed and helper states for merging windows
if (windowAssigner instanceof MergingWindowAssigner) {
// store a typed reference for the state of merging windows - sanity check
if (windowState instanceof InternalMergingState) {
windowMergingState =
(InternalMergingState<K, W, IN, IN, StateIterator<IN>, Iterable<IN>>)
windowState;
} else if (windowState != null) {
throw new IllegalStateException(
"The window uses a merging assigner, but the window state is not mergeable.");
}
@SuppressWarnings("unchecked")
final Class<Tuple2<W, W>> typedTuple = (Class<Tuple2<W, W>>) (Class<?>) Tuple2.class;
final TupleSerializer<Tuple2<W, W>> tupleSerializer =
new TupleSerializer<>(
typedTuple, new TypeSerializer[] {windowSerializer, windowSerializer});
final ListStateDescriptor<Tuple2<W, W>> mergingSetsStateDescriptor =
new ListStateDescriptor<>("merging-window-set", tupleSerializer);
// get the state that stores the merging sets
mergingSetsState =
getOrCreateKeyedState(
VoidNamespaceSerializer.INSTANCE.createInstance(),
VoidNamespaceSerializer.INSTANCE,View on GitHub (pinned to 2f3c205e92)
Solutions
- Run the job on 'hashmap' or 'rocksdb'/'forst'.
- Make the custom backend's list states implement InternalMergingState, or drop session windows for that backend.
- Keep the window state descriptor a plain ListStateDescriptor end-to-end.
- Align flink-datastream-api and flink-dist versions.
Example fix
// before: session window, two-output function, non-merging backend stream.process(twoOutputFn, WindowStrategy.session(Duration.ofMinutes(5))); // after: non-merging strategy or merging-capable backend stream.process(twoOutputFn, WindowStrategy.tumbling(Duration.ofMinutes(5), WindowStrategy.EVENT_TIME));
Defensive patterns
Strategy: validation
Validate before calling
// setup guard for two-output session jobs
if (strategy instanceof SessionWindowStrategy
&& !Arrays.asList("hashmap", "rocksdb", "forst").contains(backendName)) {
throw new IllegalArgumentException("two-output session windows need a mergeable backend");
} Type guard
static boolean requiresMergingState(WindowStrategy s) {
return s instanceof SessionWindowStrategy;
} Prevention
- Pin the state backend explicitly for session-window jobs
- Prefer non-merging strategies for two-output windows when possible
- Assert strategy/backend compatibility in job setup so failures are clear and early
When it happens
Trigger: A two-output windowed stream (e.g. WindowProcessFunction emitting to main + side collectors) built with WindowStrategy.session(...) while the keyed state for window contents is not an InternalMergingState - custom KeyedStateBackend, decorated state, or unsupported backend flavor.
Common situations: Pluggable state backends; jobs migrated from heap to a custom backend without checking merging support; mixed Flink versions; state factories wrapping returned states.
Related errors
- The window uses a merging assigner, but the window state is
- The window uses a merging assigner, but the window state is
- The end timestamp of an event-time window cannot become earl
- The end timestamp of a processing-time window cannot become
- Window {window} is not in in-flight window set.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/7c2a88897e707295.
Report an issue: GitHub.