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

  1. Pass a fraction in (0, 1.0], e.g. GPURunner(fraction=0.5).
  2. Convert percentages by dividing by 100 and clamp: fraction = min(max(pct/100, 1e-9), 1.0).
  3. Validate the configured value before constructing the runner and surface a clear config error.
  4. 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

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


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/6359fd7c9816b552. Report an issue: GitHub.