roboflow/supervision · error · ValueError

`thread_workers` must be a positive integer. Received: {thre

Error message

`thread_workers` must be a positive integer. Received: {thread_workers}

What it means

Raised by InferenceSlicer.__init__ when thread_workers is less than 1. thread_workers sets how many worker threads execute slice inference concurrently; zero or negative workers is not a meaningful thread-pool size, so construction fails.

Source

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

            Callable[[ImageType], Detections]
            | Callable[[list[npt.NDArray[Any]]], list[Detections]]
        ),
        slice_wh: int | tuple[int, int] = 640,
        overlap_wh: int | tuple[int, int] = 100,
        overlap_filter: OverlapFilter | str = OverlapFilter.NON_MAX_SUPPRESSION,
        iou_threshold: float = 0.5,
        overlap_metric: OverlapMetric | str = OverlapMetric.IOU,
        thread_workers: int = 1,
        compact_masks: bool = False,
        batch_size: int = 1,
    ):
        slice_wh_norm = self._normalize_slice_wh(slice_wh)
        overlap_wh_norm = self._normalize_overlap_wh(overlap_wh)

        self._validate_overlap(slice_wh=slice_wh_norm, overlap_wh=overlap_wh_norm)

        if thread_workers < 1:
            raise ValueError(
                "`thread_workers` must be a positive integer. "
                f"Received: {thread_workers}"
            )
        if batch_size < 1:
            raise ValueError(
                f"`batch_size` must be a positive integer. Received: {batch_size}"
            )

        self.slice_wh = slice_wh_norm
        self.overlap_wh = overlap_wh_norm
        self.iou_threshold = iou_threshold
        self.overlap_metric = OverlapMetric.from_value(overlap_metric)
        self.overlap_filter = OverlapFilter.from_value(overlap_filter)
        # Stored as single-image type; batch path calls with list[ndarray] via
        # _run_callback_batch which suppresses the arg-type mismatch there.
        self.callback: Callable[[npt.NDArray[Any]], Detections] = callback  # type: ignore[assignment]
        self.thread_workers = thread_workers
        self.compact_masks = compact_masks

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Use a positive integer, e.g. thread_workers=4, or keep the default of 1 for sequential slicing.
  2. Guard dynamic sizing: max(1, (os.cpu_count() or 1) - 1).
  3. Treat 0 not as 'auto' here — supervision has no auto mode for this parameter.

Example fix

# before
slicer = sv.InferenceSlicer(callback=cb, thread_workers=os.cpu_count() - 4)  # 0 on a 4-core-limited CI runner

# after
slicer = sv.InferenceSlicer(callback=cb, thread_workers=max(1, (os.cpu_count() or 1) - 4))
Defensive patterns

Strategy: validation

Validate before calling

import os
workers = max(1, int(cfg.get('thread_workers', 1)) or 1)
slicer = sv.InferenceSlicer(callback=cb, thread_workers=workers)

Type guard

def is_valid_thread_workers(v) -> bool:
    return isinstance(v, int) and v >= 1

Prevention

When it happens

Trigger: Constructing sv.InferenceSlicer(callback=..., thread_workers=0) or a negative value, often from a formula such as os.cpu_count() - N that underflows on small machines (cpu_count() returning 1).

Common situations: Sizing workers from CPU count with an subtraction that can hit 0 in containers or CI runners restricted to one core; config defaults left at 0 meaning 'auto' in other libraries.

Related errors


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