nolimits4web/swiper · warning

Swiper Loop Warning: Loop mode is not compatible with grid.f

Error message

Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`

What it means

Emitted by loopFix in the else-if at src/core/loop/loopFix.ts:95-96 when grid is enabled (grid.rows > 1), grid.fill === 'row', and the slide-count guard for error [3] did NOT fire (it is an else-if). Loop mode clones and repositions slides by index, but grid.fill:'row' lays slides out row-major across columns; the two layouts conflict and Swiper explicitly does not support this combination. Because it is gated behind the else-if, this warning appears only when there ARE enough slides, so a valid-looking config can still warn here.

Source

Thrown at src/core/loop/loopFix.ts:96

    ? Math.max(slidesPerGroup, Math.ceil(slidesPerView / 2))
    : slidesPerGroup;

  if (loopedSlides % slidesPerGroup !== 0) {
    loopedSlides += slidesPerGroup - (loopedSlides % slidesPerGroup);
  }
  loopedSlides += params.loopAdditionalSlides!;
  swiper.loopedSlides = loopedSlides;
  const gridEnabled = swiper.grid && params.grid && params.grid.rows! > 1;

  if (
    slides.length < slidesPerView + loopedSlides ||
    (swiper.params.effect === 'cards' && slides.length < slidesPerView + loopedSlides * 2)
  ) {
    showWarning(
      'Swiper Loop Warning: The number of slides is not enough for loop mode, it will be disabled or not function properly. You need to add more slides (or make duplicates) or lower the values of slidesPerView and slidesPerGroup parameters',
    );
  } else if (gridEnabled && params.grid!.fill === 'row') {
    showWarning('Swiper Loop Warning: Loop mode is not compatible with grid.fill = `row`');
  }

  const prependSlidesIndexes: number[] = [];
  const appendSlidesIndexes: number[] = [];

  const cols = gridEnabled ? Math.ceil(slides.length / params.grid!.rows!) : slides.length;

  const isInitialOverflow =
    initial && cols - (initialSlide as number) < slidesPerView && !bothDirections;

  let activeIndex = isInitialOverflow ? (initialSlide as number) : swiper.activeIndex;

  if (typeof activeSlideIndex === 'undefined') {
    activeSlideIndex = swiper.getSlideIndex(
      slides.find((el) => el.classList.contains(params.slideActiveClass!))!,
    );
  } else {
    activeIndex = activeSlideIndex;

View on GitHub (pinned to 6138c2a685)

Solutions

  1. Change grid.fill to 'column' (the default), which is the only fill mode compatible with loop.
  2. If you must keep grid.fill:'row', disable loop:true.
  3. Drop the grid module entirely if seamless loop is the priority.
  4. Validate the combination at config-build time (see defense) so this never reaches loopFix.

Example fix

// before -- loop + grid.fill 'row' -> warning at loopFix.ts:96
new Swiper(el, { loop: true, grid: { rows: 3, fill: 'row' } });
// after -- use the loop-compatible fill, or disable loop
new Swiper(el, { loop: true, grid: { rows: 3, fill: 'column' } }); // supported
// or: new Swiper(el, { grid: { rows: 3, fill: 'row' } }); // no loop
Defensive patterns

Strategy: validation

Validate before calling

function assertLoopGridCompatible(p: { loop?: boolean; grid?: { rows?: number; fill?: 'row' | 'column' } }): void {
  const rows = p.grid?.rows ?? 1;
  if (p.loop && rows > 1 && p.grid?.fill === 'row') {
    throw new Error('Swiper loop is incompatible with grid.fill="row"; use grid.fill="column" or disable loop.');
  }
}
assertLoopGridCompatible(params); // run before `new Swiper(el, params)`

Type guard

function isLoopGridConfigValid(p: { loop?: boolean; grid?: { rows?: number; fill?: 'row' | 'column' } }): boolean {
  return !(Boolean(p.loop) && (p.grid?.rows ?? 1) > 1 && p.grid?.fill === 'row');
}

Prevention

When it happens

Trigger: { loop:true, grid:{ rows:3, fill:'row' } } with a slide count large enough to pass the slidesPerView + loopedSlides minimum (loopFix.ts:88-91), so execution reaches the else-if at line 95. Any loop + multi-row grid with fill:'row' triggers it regardless of slide count, as long as the count minimum is satisfied.

Common situations: Wanting a multi-row looping carousel and copying a grid.fill:'row' config; reusing a grid layout preset inside a looping slider; version upgrades where grid fill semantics or the loop compatibility check changed; configs assembled from unrelated examples.

Related errors


AI-assisted analysis of nolimits4web/swiper@6138c2a685 (2026-08-12). Data as JSON: /api/errors/57cb1e1a718cefc6. Report an issue: GitHub.