{"record":{"id":"d0c2ca06050f4028","repo":"vllm-project/vllm","slug":"numa-bind-cpus-entries-must-not-be-empty","errorCode":null,"errorMessage":"numa_bind_cpus entries must not be empty.","messagePattern":"numa_bind_cpus entries must not be empty\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"vllm/config/parallel.py","lineNumber":435,"sourceCode":"        if value is None:\n            return None\n        if not value:\n            raise ValueError(\"numa_bind_nodes must not be empty.\")\n        if any(node < 0 for node in value):\n            raise ValueError(\"numa_bind_nodes must contain non-negative integers.\")\n        return value\n\n    @field_validator(\"numa_bind_cpus\")\n    @classmethod\n    def _validate_numa_bind_cpus(cls, value: list[str] | None) -> list[str] | None:\n        if value is None:\n            return None\n        if not value:\n            raise ValueError(\"numa_bind_cpus must not be empty.\")\n\n        for cpuset in value:\n            if not cpuset:\n                raise ValueError(\"numa_bind_cpus entries must not be empty.\")\n            if not _NUMACTL_CPUSET_PATTERN.fullmatch(cpuset):\n                raise ValueError(\n                    \"numa_bind_cpus entries must use numactl CPU list syntax, \"\n                    \"for example '0-3' or '0,2,4-7'.\"\n                )\n            for part in cpuset.split(\",\"):\n                if \"-\" not in part:\n                    continue\n                start_str, end_str = part.split(\"-\", 1)\n                if int(start_str) > int(end_str):\n                    raise ValueError(\n                        f\"numa_bind_cpus ranges must be ascending, but got '{cpuset}'.\"\n                    )\n        return value\n\n    @model_validator(mode=\"after\")\n    def _validate_parallel_config(self) -> Self:\n        if self._api_process_rank >= self._api_process_count:","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/vllm/config/parallel.py#L417-L453","documentation":"Inside the numa_bind_cpus list validator, each entry must be a non-empty string before regex matching. An empty-string entry (e.g. from 'a,,b' splitting or a list like ['0-3', '']) is rejected because it is neither unset (None) nor a valid CPU list.","triggerScenarios":"Passing --numa-bind-cpus 0-3,,8-11 (double comma), or programmatically ['0-3', ''] / [''] after CSV splitting.","commonSituations":"String concatenation bugs that join lists with commas when one element is empty; trailing/duplicate commas in hand-written configs.","solutions":["Remove empty segments: ensure every comma-separated entry is non-empty (no ',,' or trailing ',').","If building the list in code, filter empties before passing: [s for s in parts if s]."],"exampleFix":"# before\nvllm serve model --numa-bind-cpus 0-3,,8-11\n\n# after\nvllm serve model --numa-bind-cpus 0-3,8-11","handlingStrategy":"validation","validationCode":"def clean_cpuset_list(entries: list[str]) -> list[str]:\n    cleaned = [e.strip() for e in entries if e and e.strip()]\n    if len(cleaned) != len(entries):\n        raise SystemExit(f\"Empty numa_bind_cpus entry in {entries}\")\n    return cleaned","typeGuard":"def no_empty_cpuset_entries(entries: list[str]) -> bool:\n    return all(isinstance(e, str) and e for e in entries)","tryCatchPattern":null,"preventionTips":["Filter empties when building lists from split(',').","Reject double commas and trailing commas at config-parse time in your own tooling."],"tags":["vllm","config","numa","cpuset","parsing","validation"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}