apache/flink · critical · IllegalArgumentException

Unsupported type of window strategy : {strategyClass}

Error message

Unsupported type of window strategy : {strategyClass}

What it means

WindowUtils.createWindowAssigner translates the user-facing WindowStrategy into a runtime WindowAssigner via an instanceof chain that recognizes exactly four classes: GlobalWindowStrategy, TumblingTimeWindowStrategy, SlidingTimeWindowStrategy and SessionWindowStrategy. Any other WindowStrategy instance falls through to IllegalArgumentException during job translation, before the job ever runs. Because the check is instanceof-based (not sealed), it also fails for same-named classes loaded from a different jar version.

Source

Thrown at flink-datastream/src/main/java/org/apache/flink/datastream/impl/extension/window/utils/WindowUtils.java:68

        } else if (windowStrategy instanceof SlidingTimeWindowStrategy) {
            return ((SlidingTimeWindowStrategy) windowStrategy).getAllowedLateness().toMillis();
        } else {
            return 0;
        }
    }

    /** Create a {@link WindowAssigner} according to {@link WindowStrategy}. */
    public static WindowAssigner<?, ?> createWindowAssigner(WindowStrategy windowStrategy) {
        if (windowStrategy instanceof GlobalWindowStrategy) {
            return createGlobalWindowAssigner();
        } else if (windowStrategy instanceof TumblingTimeWindowStrategy) {
            return createTumblingTimeWindowAssigner((TumblingTimeWindowStrategy) windowStrategy);
        } else if (windowStrategy instanceof SlidingTimeWindowStrategy) {
            return createSlidingTimeWindowAssigner((SlidingTimeWindowStrategy) windowStrategy);
        } else if (windowStrategy instanceof SessionWindowStrategy) {
            return createSessionWindowAssigner((SessionWindowStrategy) windowStrategy);
        } else {
            throw new IllegalArgumentException(
                    "Unsupported type of window strategy : " + windowStrategy.getClass());
        }
    }

    /** Create window assigner for global window. */
    private static WindowAssigner<?, ?> createGlobalWindowAssigner() {
        return GlobalWindows.createWithEndOfStreamTrigger();
    }

    /** Create window assigner for tumbling time window. */
    private static WindowAssigner<?, ?> createTumblingTimeWindowAssigner(
            TumblingTimeWindowStrategy windowStrategy) {
        switch (windowStrategy.getTimeType()) {
            case PROCESSING:
                return TumblingProcessingTimeWindows.of(windowStrategy.getWindowSize());
            case EVENT:
                return TumblingEventTimeWindows.of(windowStrategy.getWindowSize());
            default:

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Build strategies only via the WindowStrategy factories: global(), tumbling(...), sliding(...), session(...).
  2. Align flink-datastream-api and flink-dist versions in the project and on the cluster; inspect the fat jar and flink/lib for duplicate strategy classes.
  3. If custom windowing is required, use a WindowAssigner-based DataStream v1 window operator instead of subclassing WindowStrategy.
  4. Log windowStrategy.getClass().getName() and its ClassLoader in job setup to confirm the instance comes from the expected jar.

Example fix

// before: custom subclass the runtime cannot map
class MyWindowStrategy extends WindowStrategy {}
stream.process(fn, new MyWindowStrategy());
// after: built-in factory
class MyWindowStrategy extends WindowStrategy {}
stream.process(fn, WindowStrategy.tumbling(Duration.ofMinutes(1), WindowStrategy.EVENT_TIME));
Defensive patterns

Strategy: type-guard

Validate before calling

// reject unknown strategies at job composition time with a clear message
if (!isSupportedStrategy(strategy)) {
    throw new IllegalArgumentException(
            "Unsupported WindowStrategy: " + strategy.getClass().getName()
                    + "; use WindowStrategy.global/tumbling/sliding/session");
}
stream.process(fn, strategy);

Type guard

static boolean isSupportedStrategy(WindowStrategy s) {
    return s instanceof GlobalWindowStrategy
            || s instanceof TumblingTimeWindowStrategy
            || s instanceof SlidingTimeWindowStrategy
            || s instanceof SessionWindowStrategy;
}

Prevention

When it happens

Trigger: Passing anything but the four built-in strategies to a windowed DataStream v2 operator: a user subclass of WindowStrategy, an instance deserialized/built from a mismatched flink-datastream jar, or a plain 'new WindowStrategy()' base instance. The throw happens when the job graph is translated, i.e. at submit time in the client or JobManager.

Common situations: Developers extending WindowStrategy hoping to add custom windowing; mixed flink-datastream-api (client) and flink-dist (cluster) versions where the strategy class is duplicated; shading/relocation producing two copies of the strategy classes.

Related errors


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