roboflow/supervision · error · ValueError
Could not place {len(images_cv2)} in grid with size: {grid_s
Error message
Could not place {len(images_cv2)} in grid with size: {grid_size}. What it means
Raised by `sv.create_tiles` when the resolved `grid_size` (rows x cols) cannot hold all images — i.e. `len(images) > rows * cols`. This only happens when you pass an explicit `grid_size` that is too small; with `grid_size=None` the function auto-negotiates a size that fits.
Source
Thrown at src/supervision/utils/image.py:856
"""
if len(images) == 0:
raise ValueError("Could not create image tiles from empty list of images.")
if return_type == "auto":
return_type = _negotiate_tiles_format(images=images)
tile_padding_color = unify_to_bgr(color=tile_padding_color)
tile_margin_color = unify_to_bgr(color=tile_margin_color)
images_cv2 = images_to_cv2(images=images)
if single_tile_size is None:
single_tile_size = _aggregate_images_shape(images=images_cv2, mode=tile_scaling)
resized_images = [
letterbox_image(
image=i, resolution_wh=single_tile_size, color=tile_padding_color
)
for i in images_cv2
]
grid_size = _establish_grid_size(images=images_cv2, grid_size=grid_size)
if len(images_cv2) > grid_size[0] * grid_size[1]:
raise ValueError(
f"Could not place {len(images_cv2)} in grid with size: {grid_size}."
)
if titles is not None:
titles = fill(sequence=titles, desired_size=len(images_cv2), content=None)
if isinstance(titles_anchors, list):
titles_anchors_sequence = titles_anchors
else:
titles_anchors_sequence = [titles_anchors]
titles_anchors = fill(
sequence=titles_anchors_sequence, desired_size=len(images_cv2), content=None
)
titles_color = unify_to_bgr(color=titles_color)
titles_background_color = unify_to_bgr(color=titles_background_color)
tiles_image = _generate_tiles(
images=resized_images,
grid_size=grid_size,
single_tile_size=single_tile_size,
tile_padding_color=tile_padding_color,View on GitHub (pinned to 7f254d9784)
Solutions
- Pass `grid_size=None` and let supervision compute a fitting grid.
- Or compute it: `cols = math.ceil(math.sqrt(len(images))); grid_size=(math.ceil(len(images)/cols), cols)`.
- Double the intended order — verify whether your tuple is (rows, cols) as expected.
Example fix
# before montage = sv.create_tiles(images=images_10, grid_size=(2, 2)) # after montage = sv.create_tiles(images=images_10, grid_size=None) # auto-fit
Defensive patterns
Strategy: validation
Validate before calling
if grid_size is not None:
rows, cols = grid_size
assert rows * cols >= len(images), f'grid {grid_size} too small for {len(images)} images' Type guard
def grid_fits(grid_size: tuple[int, int], n: int) -> bool:
rows, cols = grid_size
return rows * cols >= n Prevention
- Prefer grid_size=None and let supervision negotiate.
- Compute grid from count when you must fix it.
- Update hard-coded grids whenever the batch size changes.
When it happens
Trigger: `sv.create_tiles(images=[im]*10, grid_size=(2, 2))` — 10 images into a 2x2 grid; passing a fixed grid tuned for an earlier, smaller batch; passing columns only (e.g. `(2, None)`) where the computed rows are insufficient.
Common situations: Hard-coding grid dimensions for a fixed number of camera feeds, then adding a feed; visualizing a variable number of crops with a constant grid; confusing (rows, cols) order so the product looks larger than it is.
Related errors
- Could not create image tiles from empty list of images.
- Could not aggregate images shape - provided unknown mode: {m
- `image` must be a numpy.ndarray or PIL.Image.Image. Received
- `image` must be a numpy.ndarray or PIL.Image.Image. Received
- Data pointed by URL could not be decoded into image.
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/5f2711af91f4cab7.
Report an issue: GitHub.