apache/beam · error · IncompatibleWindowException

Only objects with the same number of months, day of month…

Error message

Only %s objects with the same number of months, day of month, start date and time zone are compatible.

What it means

CalendarWindows.MonthsWindows.verifyCompatibility throws IncompatibleWindowException when a PCollection windowed with MonthsWindows is merged with one using MonthsWindows that differ in number of months, day of month, startDate, or time zone. Beam requires identical calendar alignment for cross-source windowed grouping.

Solutions

  1. Ensure both PCollections use the identical MonthsWindows configuration before merging.
  2. Centralize the windowing definition in shared code/config.
  3. Re-window one side to match the other (assign to the target windows explicitly) before the join.
  4. Use GlobalWindows for the merge if per-calendar-window alignment is not actually required.

Example fix

// before
PCollection<A> a = inA.apply(Window.into(CalendarWindows.months(1, 15, START, ZONE)));
PCollection<B> b = inB.apply(Window.into(CalendarWindows.months(1, 1, START, ZONE)));
// after
CalendarWindows.MonthsWindows win = CalendarWindows.months(1, 15, START, ZONE);
PCollection<A> a = inA.apply(Window.into(win));
PCollection<B> b = inB.apply(Window.into(win));
Defensive patterns

Strategy: validation

Validate before calling

MonthsWindows a = CalendarWindows.months(n, dayOfMonth, START, ZONE);
MonthsWindows b = (MonthsWindows) other;
boolean compatible = a.getMonths() == b.getMonths()
    && a.getDayOfMonth() == b.getDayOfMonth()
    && a.getStartDate().equals(b.getStartDate())
    && a.getTimeZone().equals(b.getTimeZone());

Try / catch

try {
  windowFn1.verifyCompatibility(windowFn2);
} catch (IncompatibleWindowException e) {
  throw new IllegalStateException("MonthsWindows differ (months/dayOfMonth/startDate/zone)", e);
}

Prevention

When it happens

Trigger: CoGroupByKey/Join/Flatten between two PCollections whose Window.into(...) calls used CalendarWindows.months(n, ...) with differing months(), days (dayOfMonth), startDate, or timeZone.

Common situations: Monthly aggregation streams built with different month sizes (1 vs 3 months), different anchor day-of-month, or different time zones combined in one pipeline.

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/6c53a003ac7e01fe. Report an issue: GitHub.

Appendix: source

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

      return IntervalWindow.getCoder();
    }

    @Override
    public boolean isCompatible(WindowFn<?, ?> other) {
      if (!(other instanceof MonthsWindows)) {
        return false;
      }
      MonthsWindows that = (MonthsWindows) other;
      return number == that.number
          && dayOfMonth == that.dayOfMonth
          && Objects.equals(startDate, that.startDate)
          && Objects.equals(timeZone, that.timeZone);
    }

    @Override
    public void verifyCompatibility(WindowFn<?, ?> other) throws IncompatibleWindowException {
      if (!this.isCompatible(other)) {
        throw new IncompatibleWindowException(
            other,
            String.format(
                "Only %s objects with the same number of months, "
                    + "day of month, start date and time zone are compatible.",
                MonthsWindows.class.getSimpleName()));
      }
    }

    @Override
    public void populateDisplayData(DisplayData.Builder builder) {
      super.populateDisplayData(builder);

      builder
          .add(DisplayData.item("numMonths", number).withLabel("Window Months"))
          .addIfNotDefault(
              DisplayData.item("startDate", new DateTime(startDate, timeZone).toInstant())
                  .withLabel("Window Start Date"),
              new DateTime(DEFAULT_START_DATE, DateTimeZone.UTC).toInstant());

View on GitHub (pinned to 12126d8942)