sgl-project/sglang · error · ValueError

Attention backend name must be a string

Error message

Attention backend name must be a string

What it means

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.

Source

Thrown at python/sglang/multimodal_gen/runtime/server_args/server_args.py:1014

                and self.pipeline_class_name is None
                and self.num_gpus == 1
                and self.tp_size == 1
                and self.sp_degree == 1
                and self.ulysses_degree == 1
                and self.ring_degree == 1
                and self._is_ltx23_model_path(self.model_path)
            ):
                self.attention_backend = "fa"
                logger.info(
                    "Automatically set attention_backend=fa for LTX-2.3 one-stage on 1 GPU to preserve precision"
                )
                return
            self._set_default_attention_backend()

    @staticmethod
    def _normalize_attention_backend_name(backend: str) -> str:
        if not isinstance(backend, str):
            raise ValueError("Attention backend name must be a string")
        normalized = backend.strip().lower()
        if normalized in ("fa3", "fa4"):
            normalized = "fa"
        elif normalized == "cudnn_sdpa":
            normalized = "torch_cudnn_sdpa"
        try:
            return AttentionBackendEnum[normalized.upper()].name.lower()
        except KeyError:
            raise ValueError(
                f"Invalid attention backend '{backend}'. "
                f"Available options are: {[e.name.lower() for e in AttentionBackendEnum]}"
            ) from None

    @staticmethod
    def _parse_component_value_map(
        value: dict[str, Any] | str | None, *, option: str
    ) -> dict[str, str]:
        """Parse a ``component=value`` map, the same shape as component backends."""

View on GitHub (pinned to 0132848349)

Solutions

  1. Convert values to strings before passing: str(backend.value) if using an enum
  2. Filter None entries out of the component map instead of passing them through
  3. Quote backend names in YAML/JSON configs

Example fix

# before
backends = {"vision": None}
# after
backends = {"vision": "fa"}
Defensive patterns

Strategy: type-guard

Validate before calling

backends = {k: v for k, v in raw_backends.items() if isinstance(v, str) and v}
if any(not isinstance(v, str) for v in raw_backends.values()):
    raise SystemExit('component backend names must be strings')

Type guard

def all_string_backends(m: dict) -> bool:
    return all(isinstance(v, str) for v in m.values())

Prevention

When it happens

Trigger: 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).

Common situations: Programmatically building a per-component backend dict from typed config objects; a null value in JSON/YAML for one component.

Understand the failure class

Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/5ef5342b8feed2dd. Report an issue: GitHub.