unslothai/unsloth · error · ValueError
Invalid gpu_ids {requested_ids}: duplicate GPU IDs are not a
Error message
Invalid gpu_ids {requested_ids}: duplicate GPU IDs are not allowed. Parent-visible GPUs: {parent_visible_ids} What it means
Raised on the CUDA/ROCm/XPU path (after the env-var mask was confirmed numeric) when requested gpu_ids contain duplicates. The message also lists the parent-visible GPU ids so the user can see the valid id space. Distinct from the Vulkan duplicate error: this one can cross-check against the parent-visible set.
Source
Thrown at studio/backend/utils/hardware/hardware.py:2783
raise ValueError(
f"Invalid gpu_ids {requested_ids}: GPU IDs must be non-negative. "
f"Rejected IDs: {negative_ids}."
)
return requested_ids
if not parent_visible_spec["supports_explicit_gpu_ids"]:
env_var_name = (
"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:View on GitHub (pinned to 203007d190)
Solutions
- Deduplicate before calling: sorted(set(gpu_ids)) (order preserved with dict.fromkeys if order matters).
- Fix the config merge that introduced the duplicate.
- Use each physical GPU id exactly once.
Example fix
# before resolve_requested_gpu_ids([0, 0, 1]) # ValueError # after resolve_requested_gpu_ids(list(dict.fromkeys([0, 0, 1]))) # [0, 1]
Defensive patterns
Strategy: validation
Validate before calling
def dedup_ids(ids):
return list(dict.fromkeys(int(i) for i in ids))
# resolve_requested_gpu_ids(dedup_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
- Deduplicate GPU id lists at config load time.
- Avoid concatenating default + user id lists without a set merge.
- Validate ids against the parent-visible set (shown in the error) before launching jobs.
When it happens
Trigger: Calling resolve_requested_gpu_ids([0, 0]) or any list with repeats while CUDA_VISIBLE_DEVICES (or ZE_AFFINITY_MASK) is numeric or unset.
Common situations: Merging a default gpu list with a user-provided one ([0] + [0,1]); multi-select UI bugs re-submitting an id; hand-edited JSON/YAML configs; scripts appending ids in a loop without dedup.
Related errors
- 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}: 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/5affc98bac599e7e.
Report an issue: GitHub.