{"record":{"id":"c6f99fa0478b6824","repo":"unslothai/unsloth","slug":"invalid-gpu-ids-requested-ids-gpu-ids-must-be-n-c6f99f","errorCode":null,"errorMessage":"Invalid gpu_ids {requested_ids}: GPU IDs must be non-negative. Rejected IDs: {negative_ids}. Parent-visible GPUs: {parent_visible_ids}","messagePattern":"Invalid gpu_ids (.+?): GPU IDs must be non-negative\\. Rejected IDs: (.+?)\\. Parent-visible GPUs: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/utils/hardware/hardware.py","lineNumber":2791,"sourceCode":"            \"ZE_AFFINITY_MASK\" if get_device() == DeviceType.XPU else \"CUDA_VISIBLE_DEVICES\"\n        )\n        raise ValueError(\n            f\"Invalid gpu_ids {requested_ids}: explicit physical GPU IDs are \"\n            f\"unsupported when {env_var_name} uses non-numeric or subdevice \"\n            f\"entries ({parent_visible_spec['raw']!r}). Omit gpu_ids to use \"\n            \"the parent-visible devices.\"\n        )\n\n    if len(set(requested_ids)) != len(requested_ids):\n        raise ValueError(\n            f\"Invalid gpu_ids {requested_ids}: duplicate GPU IDs are not allowed. \"\n            f\"Parent-visible GPUs: {parent_visible_ids}\"\n        )\n\n    # Reject negative IDs.\n    negative_ids = [gpu_id for gpu_id in requested_ids if gpu_id < 0]\n    if negative_ids:\n        raise ValueError(\n            f\"Invalid gpu_ids {requested_ids}: GPU IDs must be non-negative. \"\n            f\"Rejected IDs: {negative_ids}. Parent-visible GPUs: {parent_visible_ids}\"\n        )\n\n    # Only enforce the physical upper bound when the count is reliable (nvidia-smi).\n    # A torch count reflects only visible devices, so it could falsely reject valid\n    # physical indices. The parent-visible check below is always authoritative.\n    if physical_gpu_count > 0 and parent_visible_ids:\n        max_parent_id = max(parent_visible_ids)\n        if physical_gpu_count > max_parent_id:\n            # Count is plausibly physical, so enforce it.\n            out_of_range = [gpu_id for gpu_id in requested_ids if gpu_id >= physical_gpu_count]\n            if out_of_range:\n                raise ValueError(\n                    f\"Invalid gpu_ids {requested_ids}: IDs must be physical GPU IDs \"\n                    f\"between 0 and {physical_gpu_count - 1}. \"\n                    f\"Rejected IDs: {out_of_range}. Parent-visible GPUs: {parent_visible_ids}\"\n                )","sourceCodeStart":2773,"sourceCodeEnd":2809,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/hardware/hardware.py#L2773-L2809","documentation":"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.","triggerScenarios":"Passing gpu_ids containing a negative value, commonly -1 imported from CUDA's 'all GPUs' convention or produced by index arithmetic underflow.","commonSituations":"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.","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."],"exampleFix":"# before\ngpu_ids = free_gpu_ids or -1  # -> ValueError\n\n# after\ngpu_ids = free_gpu_ids or []  # auto-select","handlingStrategy":"validation","validationCode":"gpu_ids = [i for i in gpu_ids if isinstance(i, int) and i >= 0]\ngpu_ids = list(dict.fromkeys(gpu_ids))\n# then resolve_requested_gpu_ids(gpu_ids)","typeGuard":"def is_valid_gpu_id_list(ids) -> bool:\n    return (\n        isinstance(ids, (list, tuple))\n        and all(isinstance(i, int) and i >= 0 for i in ids)\n        and len(set(ids)) == len(ids)\n    )","tryCatchPattern":null,"preventionTips":["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."],"tags":["gpu","cuda","hardware","validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}