apache/beam · error · IncompatibleWindowException

Sessions is only compatible with Sessions.

Error message

Sessions is only compatible with Sessions.

What it means

Sessions windowing can only be combined with other Sessions windowing that uses identical gap duration semantics; verifyCompatibility enforces this during pipeline construction when two windowfns must interact (e.g. merging side inputs or composite transforms). Passing any non-Sessions WindowFn (or mismatched Sessions) throws IncompatibleWindowException with this message.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/windowing/Sessions.java:82

  @Override
  public void mergeWindows(MergeContext c) throws Exception {
    MergeOverlappingIntervalWindows.mergeWindows(c);
  }

  @Override
  public Coder<IntervalWindow> windowCoder() {
    return IntervalWindow.getCoder();
  }

  @Override
  public boolean isCompatible(WindowFn<?, ?> other) {
    return other instanceof Sessions;
  }

  @Override
  public void verifyCompatibility(WindowFn<?, ?> other) throws IncompatibleWindowException {
    if (!this.isCompatible(other)) {
      throw new IncompatibleWindowException(
          other,
          String.format(
              "%s is only compatible with %s.",
              Sessions.class.getSimpleName(), Sessions.class.getSimpleName()));
    }
  }

  @Override
  public TypeDescriptor<IntervalWindow> getWindowTypeDescriptor() {
    return TypeDescriptor.of(IntervalWindow.class);
  }

  @Override
  public WindowMappingFn<IntervalWindow> getDefaultWindowMappingFn() {
    throw new UnsupportedOperationException("Sessions is not allowed in side inputs");
  }

  public Duration getGapDuration() {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Apply Window.into(Sessions.withGapDuration(...)) consistently to all involved PCollections
  2. Use Window.descending()/re-windowing: re-window inputs to Sessions before combining
  3. If a fixed/sliding view is needed, perform the operation per-session via Window.into matching both sides

Example fix

// before
PCollection<T> a = ...apply(Window.into(FixedWindows.of(_minutes(1))));
PCollection<T> b = ...apply(Window.into(Sessions.withGapDuration(_minutes(5))));
KeyedPCollectionTuple.of(...) // IncompatibleWindowException
// after
PCollection<T> a2 = a.apply(Window.into(Sessions.withGapDuration(_minutes(5))));
Defensive patterns

Strategy: validation

Validate before calling

if (!(windowFnA instanceof Sessions) || !(windowFnB instanceof Sessions)) throw new IllegalArgumentException("Both PCollections must use Sessions windowing");

Type guard

boolean sessionsCompatible(WindowFn<?,?> a, WindowFn<?,?> b) { return a instanceof Sessions && b instanceof Sessions; }

Try / catch

try { pipeline.apply(combine); } catch (IncompatibleWindowException e) { reWindowAllInputs(Sessions.withGapDuration(gap)); }

Prevention

When it happens

Trigger: Calling Sessions.verifyCompatibility(other) where other is not a Sessions instance, e.g. Window.into(Sessions.withGapDuration(...)) combined in a transform with FixedWindows/SlidingWindows inputs.

Common situations: Joining or flattening PCollections windowed differently; applying a composite transform that requires uniform windowing; mistakenly applying Window.into() twice with different windowfns on the same stream.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/c0d752d49e84ace0. Report an issue: GitHub.