{"record":{"id":"853bda3135a6a37d","repo":"sgl-project/sglang","slug":"component-attention-backend-key-must-not-be-empty","errorCode":null,"errorMessage":"Component attention backend key must not be empty","messagePattern":"Component attention backend key must not be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/server_args/server_args.py","lineNumber":1138,"sourceCode":"                raise ValueError(\n                    \"component_attention_backends must use component=backend entries\"\n                )\n            component, backend = pair.split(\"=\", 1)\n            result[component.strip()] = backend.strip()\n        return result\n\n    @classmethod\n    def _normalize_component_attention_backends(\n        cls, value: dict[str, str] | str | None\n    ) -> dict[str, str]:\n        raw = cls._parse_component_attention_backend_map(value)\n        normalized: dict[str, str] = {}\n        for component, backend in raw.items():\n            if not isinstance(component, str):\n                raise ValueError(\"Component attention backend key must be a string\")\n            component_name = component.strip().replace(\"-\", \"_\")\n            if not component_name:\n                raise ValueError(\"Component attention backend key must not be empty\")\n            normalized[component_name] = cls._normalize_attention_backend_name(backend)\n        return normalized\n\n    def resolve_component_attention_backend(\n        self, *component_names: str | None\n    ) -> tuple[AttentionBackendEnum | None, str | None]:\n        for component_name in component_names:\n            if component_name is None:\n                continue\n            key = component_name.replace(\"-\", \"_\")\n            fallback_keys = [key]\n            if key.endswith(\"_2\"):\n                # Secondary two-stage components inherit the base component\n                # backend unless explicitly overridden.\n                fallback_keys.append(key[:-2])\n            for backend_key in fallback_keys:\n                backend = self.component_attention_backends.get(backend_key)\n                if backend is not None:","sourceCodeStart":1120,"sourceCodeEnd":1156,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/server_args/server_args.py#L1120-L1156","documentation":"A component-attention-backend entry whose key strips/normalizes to the empty string (e.g. ' ', '-', or '=flash') is rejected because there is no component to assign the backend to.","triggerScenarios":"Passing 'dit=flash,=sdpa' or a dict key of '-' (hyphen-only, which normalize replaces with '_' leaving an empty-ish name), or whitespace-only key.","commonSituations":"Trailing 'x=' style entries from malformed comma lists; accidental empty key in generated configs.","solutions":["Remove empty component entries from the string/dict","Check for keys that are only whitespace or hyphens","Validate the map before constructing ServerArgs"],"exampleFix":"# before\n--component-attention-backends dit=flash,=sdpa\n# after\n--component-attention-backends dit=flash","handlingStrategy":"validation","validationCode":"assert all(k.strip() and k.strip().replace('-', '_') for k in backends), 'empty component key'","typeGuard":"def no_empty_keys(d: dict[str, str]) -> bool:\n    return all(k.strip().replace('-', '_') for k in d)","tryCatchPattern":null,"preventionTips":["Drop empty entries when merging config maps"],"tags":["config","validation","attention-backend"],"backgroundTag":"empty-config-key","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}