apache/beam · error · IllegalArgumentException

FixedWindows WindowingStrategies must have 0 <= offset <…

Error message

FixedWindows WindowingStrategies must have 0 <= offset < size

What it means

FixedWindows.of(...).withOffset(Duration) constructs a FixedWindows whose offset must satisfy 0 <= offset < size. The private constructor validates this and throws IllegalArgumentException otherwise, because an offset >= size is equivalent to a different window size and would corrupt window alignment.

Solutions

  1. Ensure offset >= Duration.ZERO and strictly less than the window size before calling withOffset.
  2. If the desired offset exceeds size, shrink it modulo the size (offset % size) or redefine the window size.
  3. Validate user-provided size/offset config at startup with a clear error message.
  4. Use Durations.ofX helpers consistently to avoid unit mistakes between size and offset.

Example fix

// before
Duration size = Durations.minutes(5);
Duration offset = Durations.minutes(10); // offset >= size -> IllegalArgumentException
FixedWindows win = FixedWindows.of(size).withOffset(offset);
// after
Duration offset = Durations.minutes(3);
checkArgument(offset.isShorterThan(size) && !offset.isShorterThan(Duration.ZERO), "0 <= offset < size");
FixedWindows win = FixedWindows.of(size).withOffset(offset);
Defensive patterns

Strategy: validation

Validate before calling

public static FixedWindows safeFixedWindows(Duration size, Duration offset) {
  checkArgument(!offset.isShorterThan(Duration.ZERO), "offset must be >= 0");
  checkArgument(offset.isShorterThan(size), "offset must be < size (got %s >= %s)", offset, size);
  return FixedWindows.of(size).withOffset(offset);
}

Try / catch

try {
  return FixedWindows.of(size).withOffset(offset);
} catch (IllegalArgumentException e) {
  LOG.warn("Invalid fixed-window offset {} for size {}; using offset %% size", offset, size);
  return FixedWindows.of(size).withOffset(offset.minus(size.dividedBy(
      size.getMillis() <= 0 ? 1 : size.getMillis() / Math.max(1, size.getMillis() / Math.max(1, offset.getMillis() / size.getMillis() == 0 ? 1 : 0)))));
}

Prevention

When it happens

Trigger: Calling FixedWindows.of(Duration.ofMinutes(5)).withOffset(Duration.ofMinutes(10)) or withOffset(Duration.ofMinutes(-1)) — negative offset, or offset equal to or larger than the window size.

Common situations: Building windows from user-supplied config where offset and size come from separate settings without a cross-check; passing offset in the wrong unit (seconds vs minutes) so it silently exceeds the size.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

   * where 0 is the epoch.
   */
  public static FixedWindows of(Duration size) {
    return new FixedWindows(size, Duration.ZERO);
  }

  /**
   * Partitions the timestamp space into half-open intervals of the form [N * size + offset, (N + 1)
   * * size + offset), where 0 is the epoch.
   *
   * @throws IllegalArgumentException if offset is not in [0, size)
   */
  public FixedWindows withOffset(Duration offset) {
    return new FixedWindows(size, offset);
  }

  private FixedWindows(Duration size, Duration offset) {
    if (offset.isShorterThan(Duration.ZERO) || !offset.isShorterThan(size)) {
      throw new IllegalArgumentException(
          "FixedWindows WindowingStrategies must have 0 <= offset < size");
    }
    this.size = size;
    this.offset = offset;
  }

  @Override
  public IntervalWindow assignWindow(Instant timestamp) {
    Instant start =
        new Instant(
            timestamp.getMillis()
                - timestamp.plus(size).minus(offset).getMillis() % size.getMillis());

    // The global window is inclusive of max timestamp, while interval window excludes its
    // upper bound
    Instant endOfGlobalWindow = GlobalWindow.INSTANCE.maxTimestamp().plus(Duration.millis(1));

    // The end of the window is either start + size if that is within the allowable range, otherwise

View on GitHub (pinned to 12126d8942)