roboflow/supervision · error · ValueError

The number of images exceeds the grid size. Please increase

Error message

The number of images exceeds the grid size. Please increase the grid size or reduce the number of images.

What it means

Raised by plot_images_grid() in supervision.utils.notebook when len(images) exceeds nrows*ncols of the requested grid_size. The helper lays images onto a fixed matplotlib grid, so extra images have nowhere to go and it fails fast instead of silently dropping them.

Source

Thrown at src/supervision/utils/notebook.py:101

        >>> from PIL import Image
        >>> image1 = np.zeros((100, 100, 3), dtype=np.uint8)
        >>> image2 = Image.new('RGB', (100, 100))
        >>> image3 = np.zeros((100, 100, 3), dtype=np.uint8)
        >>> images = [image1, image2, image3]
        >>> titles = ["Image 1", "Image 2", "Image 3"]
        >>> sv.plot_images_grid(images, grid_size=(2, 2), titles=titles, size=(16, 16))
        ...

        ```
    """
    nrows, ncols = grid_size

    images_np: list[npt.NDArray[np.uint8]] = [
        pillow_to_cv2(img) if isinstance(img, Image.Image) else img for img in images
    ]

    if len(images_np) > nrows * ncols:
        raise ValueError(
            "The number of images exceeds the grid size. Please increase the grid size"
            " or reduce the number of images."
        )

    # Keep pyplot lazy so importing notebook helpers does not import matplotlib.
    import matplotlib.pyplot as plt

    _fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=size)

    for idx, ax in enumerate(axes.flat):
        if idx < len(images_np):
            if images_np[idx].ndim == 2:
                ax.imshow(images_np[idx], cmap=cmap)
            else:
                ax.imshow(cv2.cvtColor(images_np[idx], cv2.COLOR_BGR2RGB))

            if titles is not None and idx < len(titles):
                ax.set_title(titles[idx])

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Derive the grid from the image count: grid_size=(ceil(n / cols), cols).
  2. Trim the images to fit: images[:nrows*ncols].
  3. If you swapped the tuple, remember grid_size is (nrows, ncols), not (width, height).

Example fix

// before
sv.plot_images_grid(images, grid_size=(2, 2))  # 7 images -> ValueError

// after
cols = 4
rows = math.ceil(len(images) / cols)
sv.plot_images_grid(images, grid_size=(rows, cols))
Defensive patterns

Strategy: validation

Validate before calling

n = len(images)
rows = math.ceil(n / ncols)
assert rows * ncols >= n
sv.plot_images_grid(images, grid_size=(rows, ncols))

Try / catch

try:
    sv.plot_images_grid(images, grid_size=grid)
except ValueError as e:
    if 'exceeds the grid size' in str(e):
        images = images[: grid[0] * grid[1]]
        sv.plot_images_grid(images, grid_size=grid)
    else:
        raise

Prevention

When it happens

Trigger: Calling sv.plot_images_grid(images, grid_size=(2, 2)) with 5+ images; computing grid_size from a stale count after appending images; passing a (rows, cols) tuple where rows and cols are swapped relative to intent.

Common situations: Visualizing a dynamic batch of frames or dataset samples with a hardcoded grid; dataset size changes between runs while grid_size stays fixed; off-by-one when deriving cols = n // rows and n is not divisible.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/1ffd7c700f58c5c8. Report an issue: GitHub.