sgl-project/sglang · error · ValueError
op {op!r} has multiple backends usable on device {platform.d
Error message
op {op!r} has multiple backends usable on device {platform.device.value!r} ({[s.backend.value for s in eligible]}); pass backend=... to choose one What it means
Raised when an op has multiple backends that are ALL eligible on the current device and the caller did not pass backend=. Because selection would be ambiguous, sglang refuses to pick and asks for an explicit choice. This is the documented disambiguation error from select_kernel.
Source
Thrown at python/sglang/kernels/selector.py:80
for spec in specs:
if spec.backend == backend:
return spec
raise KeyError(f"No '{backend.value}' backend registered for op {op!r}")
if len(specs) == 1:
return specs[0]
# Multiple backends: hard-filter by device eligibility.
platform = _platform()
eligible = [s for s in specs if s.is_available(platform)]
if len(eligible) == 1:
return eligible[0]
if not eligible:
raise ValueError(
f"op {op!r} has no backend usable on device {platform.device.value!r} "
f"(registered: {[s.backend.value for s in specs]})"
)
raise ValueError(
f"op {op!r} has multiple backends usable on device "
f"{platform.device.value!r} ({[s.backend.value for s in eligible]}); "
f"pass backend=... to choose one"
)
@lru_cache(maxsize=None)
def _resolve(op: str, backend: Optional[KernelBackend]) -> Callable:
return select_kernel(op, backend=backend).load()
def get_kernel(op: str, backend: Optional[KernelBackend] = None) -> Callable:
"""Resolve ``op`` to a callable kernel and cache it.
This is what the public ``sglang.kernels.ops.*`` wrappers call. The first
call resolves and imports the backend; later calls hit the cache.
"""
return _resolve(op, backend)View on GitHub (pinned to 0132848349)
Solutions
- Pass backend=Backend.X explicitly to select_kernel for this op.
- Expose a backend override in your config (env var / CLI flag) so users on multi-backend hosts can choose.
- If one backend should always win, register only it, or wrap resolution with your own priority ordering.
Example fix
# before spec = select_kernel(op) # after from sglang.kernels import Backend spec = select_kernel(op, backend=Backend.FLASHINFER)
Defensive patterns
Strategy: validation
Validate before calling
from sglang.kernels.registry import registry
from sglang.kernels.platform import _platform
p = _platform()
eligible = [s for s in registry.get(op, []) if s.is_available(p)]
if len(eligible) > 1:
spec = select_kernel(op, backend=eligible[0].backend) # or user-chosen
else:
spec = select_kernel(op) Try / catch
try:
spec = select_kernel(op)
except ValueError as e:
if 'multiple backends' in str(e):
spec = select_kernel(op, backend=DEFAULT_BACKEND)
else:
raise Prevention
- Expose a backend config knob (env var) in multi-backend deployments.
- Wrap resolution once in a helper with an explicit priority list.
When it happens
Trigger: select_kernel(op) where registry has >=2 specs (e.g. triton and flashinfer) and both is_available(platform) checks pass — typical in tests like test_multi_backend_requires_explicit_backend and on fully-provisioned GPU hosts.
Common situations: Benchmarking or portability code that calls the generic resolver on a machine with several backends installed; new ops that register a second backend without a priority mechanism.
Related errors
- No '{backend.value}' backend registered for op {op!r}
- Multiple serve backends matched this request: {names}. Selec
- No kernels registered for op {op!r}
- op {op!r} has no backend usable on device {platform.device.v
- KernelSpec.target must be 'module:attr', got {self.target!r}
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/35176eac9eaf075f.
Report an issue: GitHub.