{"record":{"id":"7b2b064eb5c75833","repo":"cocoindex-io/cocoindex","slug":"num-gpus-must-be-1-got-num-gpus","errorCode":null,"errorMessage":"num_gpus must be >= 1, got {num_gpus}","messagePattern":"num_gpus must be >= 1, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/runner.py","lineNumber":278,"sourceCode":"    \"\"\"Tracks fractional GPU capacity across multiple GPUs.\n\n    Each GPU starts with capacity 1.0. ``acquire(fraction)`` blocks until a\n    GPU with enough remaining capacity is available, then returns its id.\n    ``release(gpu_id, fraction)`` restores capacity and wakes waiters.\n\n    The default pool size is auto-detected from ``COCOINDEX_NUM_GPUS``,\n    ``CUDA_VISIBLE_DEVICES``, or ``nvidia-smi`` (falling back to 1).\n    Call ``configure_gpu_pool(N)`` to override programmatically.\n    \"\"\"\n\n    _num_gpus: int\n    _capacity: list[float]\n    _cond: asyncio.Condition | None\n    _bound_loop: asyncio.AbstractEventLoop | None\n\n    def __init__(self, num_gpus: int) -> None:\n        if num_gpus < 1:\n            raise ValueError(f\"num_gpus must be >= 1, got {num_gpus}\")\n        self._num_gpus = num_gpus\n        self._capacity = [1.0] * num_gpus\n        self._cond = None\n        self._bound_loop = None\n\n    @property\n    def num_gpus(self) -> int:\n        return self._num_gpus\n\n    def _get_cond(self) -> asyncio.Condition:\n        loop = asyncio.get_running_loop()\n        if self._cond is None or self._bound_loop is not loop:\n            self._cond = asyncio.Condition()\n            self._bound_loop = loop\n        return self._cond\n\n    def _find_available(self, fraction: float) -> int | None:\n        best_gpu = None","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/runner.py#L260-L296","documentation":"Constructor validation of the GPU-arbitration pool size. _GpuPool tracks one fractional capacity slot per GPU, and initialize with 0 or negative GPUs would leave the pool permanently unable to satisfy any acquire() request (callers would block forever). This ValueError fires when configure_gpu_pool(N) or the auto-detected pool size yields N < 1 — e.g. a mistyped COCOINDEX_NUM_GPUS environment variable. Pass an integer >= 1.","triggerScenarios":"Calling GPURunner(num_gpus=0), a negative value, or passing a computed value that evaluates to 0 (e.g. len(gpus) on an empty detection list).","commonSituations":"Auto-configuring from torch.cuda.device_count() or nvidia-smi output on a machine without GPUs, or reading an unset/zero environment variable such as NUM_GPUS=0.","solutions":["Pass an integer >= 1: GPURunner(num_gpus=1).","Validate the computed GPU count before construction and fall back to CPU execution when it is 0.","Check that the machine actually has GPUs and drivers are installed so detection returns a positive count.","Fix the environment variable or config file supplying the GPU count."],"exampleFix":"// before\ngpus = int(os.environ.get(\"NUM_GPUS\", \"0\"))\nrunner = GPURunner(num_gpus=gpus)  # ValueError\n\n// after\nnum_gpus = int(os.environ.get(\"NUM_GPUS\", \"1\"))\nif num_gpus < 1:\n    raise SystemExit(\"No GPUs configured; set NUM_GPUS>=1 or use CPU runner\")\nrunner = GPURunner(num_gpus=num_gpus)","handlingStrategy":"validation","validationCode":"if not isinstance(num_gpus, int) or num_gpus < 1:\n    raise ValueError(f\"num_gpus must be >= 1, got {num_gpus}\")","typeGuard":"def valid_gpu_count(n: object) -> bool:\n    return isinstance(n, int) and not isinstance(n, bool) and n >= 1","tryCatchPattern":"try:\n    runner = GPURunner(num_gpus=num_gpus)\nexcept ValueError:\n    runner = CPURunner()  # or fail fast with a clear config message","preventionTips":["Validate GPU counts from environment/config before constructing the runner","Use a positive default (1) rather than 0 when detection is unavailable","Confirm GPUs exist on the host (nvidia-smi) before auto-configuring"],"tags":["python","gpu","validation","value-error"],"backgroundTag":"value-out-of-range","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}