cocoindex-io/cocoindex · error · ValueError
fraction must be in (0, 1.0], got {fraction}
Error message
fraction must be in (0, 1.0], got {fraction} What it means
GPURunner supports fractional GPU allocation (e.g. MIG-style shares) but a fraction must be a positive value no greater than 1.0. Values outside (0, 1.0] — 0, negative, NaN, or >1 — raise a ValueError at construction.
Source
Thrown at python/cocoindex/_internal/runner.py:407
``coco.GPU`` is shorthand for ``GPURunner(fraction=1.0)``.
``coco.GPU(0.5)`` creates a runner requesting half a GPU.
The assigned GPU id(s) are available inside the function via
``coco.current_gpu()`` (first id) and ``coco.current_gpus()`` (full list).
The allocated fraction is available via ``coco.current_gpu_fraction()``.
For multi-GPU subprocess mode (where ``CUDA_VISIBLE_DEVICES`` must be set
per-process), use in-process mode (the default) until per-GPU subprocess
pools are implemented.
"""
_fraction: float
_use_subprocess: bool | None
_gpu_executor: ThreadPoolExecutor | None
def __init__(self, fraction: float = 1.0) -> None:
super().__init__()
if not (0 < fraction <= 1.0):
raise ValueError(f"fraction must be in (0, 1.0], got {fraction}")
self._fraction = fraction
self._use_subprocess = None
self._gpu_executor = None
def __call__(self, fraction: float = 1.0) -> GPURunner:
return GPURunner(fraction=fraction)
def _should_use_subprocess(self) -> bool:
"""Check if subprocess mode is enabled (reads env var lazily on first call)."""
if self._use_subprocess is None:
self._use_subprocess = (
os.environ.get("COCOINDEX_RUN_GPU_IN_SUBPROCESS") == "1"
)
return self._use_subprocess
def _get_gpu_executor(self) -> ThreadPoolExecutor:
"""Get or create the dedicated GPU thread pool."""
if self._gpu_executor is None:View on GitHub (pinned to e84aa99b32)
Solutions
- Pass a fraction in (0, 1.0], e.g. GPURunner(fraction=0.5).
- Convert percentages by dividing by 100 and clamp: fraction = min(max(pct/100, 1e-9), 1.0).
- Validate the configured value before constructing the runner and surface a clear config error.
- Guard against NaN/zero results from upstream division in your config loading.
Example fix
// before pct = cfg["gpu_share"] # e.g. 150 runner = GPURunner(fraction=pct) # ValueError // after fraction = min(max(cfg["gpu_share_pct"] / 100.0, 1e-9), 1.0) runner = GPURunner(fraction=fraction)
Defensive patterns
Strategy: validation
Validate before calling
import math
if not (isinstance(fraction, float) and math.isfinite(fraction) and 0 < fraction <= 1.0):
raise ValueError(f"fraction must be in (0, 1.0], got {fraction}") Type guard
def valid_fraction(x: object) -> bool:
return isinstance(x, (int, float)) and math.isfinite(x) and 0 < x <= 1.0 Try / catch
try:
runner = GPURunner(fraction=fraction)
except ValueError as e:
logging.error("bad GPU fraction: %s", e)
runner = GPURunner(fraction=1.0) Prevention
- Store fractions (0.5), never percentages (50), in config
- Clamp computed shares to (0, 1.0] after division
- Check for NaN when the value is computed dynamically
When it happens
Trigger: GPURunner(fraction=0), GPURunner(fraction=1.5), GPURunner(fraction=-0.2), or a float('nan') passed from config or a percentage conversion bug (e.g. 150 passed instead of 1.5 meaning 150%).
Common situations: Confusing percentages with fractions (passing 150 instead of 1.5 or 0.5 instead of 50), dividing by zero when computing the share, or parsing an invalid config value.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- num_gpus must be >= 1, got {num_gpus}
- expected None{loc}, got {type(value).__name__}
- expected {tp}{loc}, got {type(value).__name__}: {value!r}
- expected tuple{loc}, got {type(value).__name__}
- expected {tp}{loc}, got {type(value).__name__}
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/6359fd7c9816b552.
Report an issue: GitHub.