unslothai/unsloth · error · ValueError
Invalid gpu_ids {requested_ids}: GPU IDs must be non-negativ
Error message
Invalid gpu_ids {requested_ids}: GPU IDs must be non-negative. Rejected IDs: {negative_ids}. Parent-visible GPUs: {parent_visible_ids} What it means
Raised on the CUDA/ROCm/XPU path when any requested gpu_id is negative; rejected ids and the parent-visible set are both included in the message. It runs after the duplicate check, so [0, -1] first fails as a duplicate-free but negative-containing list here.
Source
Thrown at studio/backend/utils/hardware/hardware.py:2791
"ZE_AFFINITY_MASK" if get_device() == DeviceType.XPU else "CUDA_VISIBLE_DEVICES"
)
raise ValueError(
f"Invalid gpu_ids {requested_ids}: explicit physical GPU IDs are "
f"unsupported when {env_var_name} uses non-numeric or subdevice "
f"entries ({parent_visible_spec['raw']!r}). Omit gpu_ids to use "
"the parent-visible devices."
)
if len(set(requested_ids)) != len(requested_ids):
raise ValueError(
f"Invalid gpu_ids {requested_ids}: duplicate GPU IDs are not allowed. "
f"Parent-visible GPUs: {parent_visible_ids}"
)
# Reject negative IDs.
negative_ids = [gpu_id for gpu_id in requested_ids if gpu_id < 0]
if negative_ids:
raise ValueError(
f"Invalid gpu_ids {requested_ids}: GPU IDs must be non-negative. "
f"Rejected IDs: {negative_ids}. Parent-visible GPUs: {parent_visible_ids}"
)
# Only enforce the physical upper bound when the count is reliable (nvidia-smi).
# A torch count reflects only visible devices, so it could falsely reject valid
# physical indices. The parent-visible check below is always authoritative.
if physical_gpu_count > 0 and parent_visible_ids:
max_parent_id = max(parent_visible_ids)
if physical_gpu_count > max_parent_id:
# Count is plausibly physical, so enforce it.
out_of_range = [gpu_id for gpu_id in requested_ids if gpu_id >= physical_gpu_count]
if out_of_range:
raise ValueError(
f"Invalid gpu_ids {requested_ids}: IDs must be physical GPU IDs "
f"between 0 and {physical_gpu_count - 1}. "
f"Rejected IDs: {out_of_range}. Parent-visible GPUs: {parent_visible_ids}"
)View on GitHub (pinned to 203007d190)
Solutions
- Use None or [] for auto-selection instead of -1.
- Clamp/validate ids to 0..N-1 before passing them.
- Fix the 'find free GPU' helper to return None when no GPU is free and handle that case.
Example fix
# before gpu_ids = free_gpu_ids or -1 # -> ValueError # after gpu_ids = free_gpu_ids or [] # auto-select
Defensive patterns
Strategy: validation
Validate before calling
gpu_ids = [i for i in gpu_ids if isinstance(i, int) and i >= 0] gpu_ids = list(dict.fromkeys(gpu_ids)) # then resolve_requested_gpu_ids(gpu_ids)
Type guard
def is_valid_gpu_id_list(ids) -> bool:
return (
isinstance(ids, (list, tuple))
and all(isinstance(i, int) and i >= 0 for i in ids)
and len(set(ids)) == len(ids)
) Prevention
- Use None or [] for auto-selection; reserve no negative sentinels.
- Make 'find free GPU' helpers return None on failure and handle it explicitly.
- Validate ids against nvidia-smi output before submitting jobs.
When it happens
Trigger: Passing gpu_ids containing a negative value, commonly -1 imported from CUDA's 'all GPUs' convention or produced by index arithmetic underflow.
Common situations: Scripts that set gpu_ids=-1 to mean 'use everything'; default sentinel values of -1 leaking from config parsing; -1 returned from a 'find free gpu' helper when none found.
Related errors
- Invalid gpu_ids {requested_ids}: duplicate GPU IDs are not a
- Invalid gpu_ids {requested_ids}: duplicate GPU IDs are not a
- Invalid gpu_ids {requested_ids}: GPU IDs must be non-negativ
- Invalid gpu_ids {requested_ids}: IDs must be physical GPU ID
- GPU selection is unavailable on this host: {exc}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/c6f99fa0478b6824.
Report an issue: GitHub.