{"record":{"id":"5ef5342b8feed2dd","repo":"sgl-project/sglang","slug":"attention-backend-name-must-be-a-string","errorCode":null,"errorMessage":"Attention backend name must be a string","messagePattern":"Attention backend name must be a string","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/server_args/server_args.py","lineNumber":1014,"sourceCode":"                and self.pipeline_class_name is None\n                and self.num_gpus == 1\n                and self.tp_size == 1\n                and self.sp_degree == 1\n                and self.ulysses_degree == 1\n                and self.ring_degree == 1\n                and self._is_ltx23_model_path(self.model_path)\n            ):\n                self.attention_backend = \"fa\"\n                logger.info(\n                    \"Automatically set attention_backend=fa for LTX-2.3 one-stage on 1 GPU to preserve precision\"\n                )\n                return\n            self._set_default_attention_backend()\n\n    @staticmethod\n    def _normalize_attention_backend_name(backend: str) -> str:\n        if not isinstance(backend, str):\n            raise ValueError(\"Attention backend name must be a string\")\n        normalized = backend.strip().lower()\n        if normalized in (\"fa3\", \"fa4\"):\n            normalized = \"fa\"\n        elif normalized == \"cudnn_sdpa\":\n            normalized = \"torch_cudnn_sdpa\"\n        try:\n            return AttentionBackendEnum[normalized.upper()].name.lower()\n        except KeyError:\n            raise ValueError(\n                f\"Invalid attention backend '{backend}'. \"\n                f\"Available options are: {[e.name.lower() for e in AttentionBackendEnum]}\"\n            ) from None\n\n    @staticmethod\n    def _parse_component_value_map(\n        value: dict[str, Any] | str | None, *, option: str\n    ) -> dict[str, str]:\n        \"\"\"Parse a ``component=value`` map, the same shape as component backends.\"\"\"","sourceCodeStart":996,"sourceCodeEnd":1032,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/server_args/server_args.py#L996-L1032","documentation":"Static helper _normalize_attention_backend_name requires its argument to be a str; anything else (int, None, enum object) raises before normalization. Used by _normalize_component_attention_backends for per-component backend names.","triggerScenarios":"Passing a component backend map like {'text_encoder': None} or an AttentionBackendEnum member directly instead of its string name; YAML parsing producing non-string scalars (e.g. unquoted numbers).","commonSituations":"Programmatically building a per-component backend dict from typed config objects; a null value in JSON/YAML for one component.","solutions":["Convert values to strings before passing: str(backend.value) if using an enum","Filter None entries out of the component map instead of passing them through","Quote backend names in YAML/JSON configs"],"exampleFix":"# before\nbackends = {\"vision\": None}\n# after\nbackends = {\"vision\": \"fa\"}","handlingStrategy":"type-guard","validationCode":"backends = {k: v for k, v in raw_backends.items() if isinstance(v, str) and v}\nif any(not isinstance(v, str) for v in raw_backends.values()):\n    raise SystemExit('component backend names must be strings')","typeGuard":"def all_string_backends(m: dict) -> bool:\n    return all(isinstance(v, str) for v in m.values())","tryCatchPattern":null,"preventionTips":["Convert enum members via .value before passing","Quote backend names in YAML/JSON to avoid type coercion"],"tags":["attention-backend","type-validation","config"],"backgroundTag":"wrong-argument-type","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}