roboflow/supervision · error · ValueError

Callback returned {len(detections_in_slices)} Detections for

Error message

Callback returned {len(detections_in_slices)} Detections for {len(offsets)} slices. Lengths must match.

What it means

Raised by InferenceSlicer's batch path when the callback's returned list length differs from the number of image slices passed in. The slicer must zip each returned Detections with its slice offset to map detections back into full-image coordinates; a mismatched length breaks that 1:1 alignment, so it fails instead of silently dropping or misplacing detections.

Source

Thrown at src/supervision/detection/tools/inference_slicer.py:591

                with self._raster_read_lock:
                    bands = image.read(window=window)
                slices.append(np.ascontiguousarray(np.transpose(bands, (1, 2, 0))))
            resolution_wh = (image.width, image.height)
        else:
            slices = [crop_image(image=image, xyxy=offset) for offset in offsets]
            resolution_wh = get_image_resolution_wh(image)

        batch_callback = cast(
            Callable[[list[npt.NDArray[Any]]], list[Detections]], self.callback
        )
        detections_in_slices = batch_callback(slices)
        if not isinstance(detections_in_slices, list):
            raise ValueError(
                "Callback must return `list[Detections]` when `batch_size > 1`. "
                f"Got: {type(detections_in_slices)}"
            )
        if len(detections_in_slices) != len(offsets):
            raise ValueError(
                f"Callback returned {len(detections_in_slices)} Detections "
                f"for {len(offsets)} slices. Lengths must match."
            )

        if self.compact_masks:
            for det, image_slice in zip(detections_in_slices, slices):
                if det.mask is not None and isinstance(det.mask, np.ndarray):
                    slice_w, slice_h = get_image_resolution_wh(image_slice)
                    full_slice_xyxy = np.tile(
                        np.array([[0, 0, slice_w - 1, slice_h - 1]], dtype=np.float64),
                        (len(det), 1),
                    )
                    det.mask = CompactMask.from_dense(
                        det.mask,
                        full_slice_xyxy,
                        image_shape=(slice_h, slice_w),
                    )

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Always return exactly one Detections (possibly empty, sv.Detections.empty()) per input image, in input order.
  2. If the model API can skip images, index-pad the results back to the input length before returning.
  3. Do not filter slices inside the callback — filtering happens later via the slicer's overlap/NMS stages.

Example fix

# before
def callback(images):
    return [sv.Detections.from_ultralytics(r) for r in model.predict(images) if len(r.boxes) > 0]

# after
def callback(images):
    return [sv.Detections.from_ultralytics(r) for r in model.predict(images)]  # empty slices yield empty Detections
Defensive patterns

Strategy: validation

Validate before calling

def batch_callback(images):
    results = model.predict(images, verbose=False)
    if len(results) != len(images):
        raise RuntimeError(f'model returned {len(results)} results for {len(images)} images')
    return [sv.Detections.from_ultralytics(r) for r in results]

Type guard

def matches_slice_count(result, images) -> bool:
    return isinstance(result, list) and len(result) == len(images)

Try / catch

try:
    detections = slicer(image)
except ValueError as err:
    if 'Lengths must match' in str(err):
        raise RuntimeError('batch callback must return one Detections per input slice') from err
    raise

Prevention

When it happens

Trigger: A batch callback that returns model predictions for a filtered subset (e.g. only images with detections), or a predict call that returns fewer Results than inputs (some backends skip failed images), or returning e.g. results[:-1] by an off-by-one bug.

Common situations: Callbacks that filter empty results; batched inference wrappers that deduplicate or drop failed items; misunderstanding that one Detections per input slice is required even when a slice has zero detections.

Related errors


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