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
- Ensure both PCollections use the identical MonthsWindows configuration before merging.
- Centralize the windowing definition in shared code/config.
- Re-window one side to match the other (assign to the target windows explicitly) before the join.
- 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
- Centralize MonthsWindows construction in one factory.
- Pin dayOfMonth and timeZone in config for all monthly streams.
- Run verifyCompatibility checks in pipeline-construction tests.
- Re-window inputs explicitly before merging if configs can diverge.
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
- GlobalWindows is only compatible with GlobalWindows.
- Only FixedWindows objects with the same size and offset are…
- Only objects with the same number of days, start date and…
- Only objects with the same number of years, month of year…
- Attempted to get side input window for GlobalWindow from…
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)