{"record":{"id":"35176eac9eaf075f","repo":"sgl-project/sglang","slug":"op-op-r-has-multiple-backends-usable-on-device","errorCode":null,"errorMessage":"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","messagePattern":"op (.+?) has multiple backends usable on device (.+?) \\((.+?)\\); pass backend=\\.\\.\\. to choose one","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/kernels/selector.py","lineNumber":80,"sourceCode":"        for spec in specs:\n            if spec.backend == backend:\n                return spec\n        raise KeyError(f\"No '{backend.value}' backend registered for op {op!r}\")\n\n    if len(specs) == 1:\n        return specs[0]\n\n    # Multiple backends: hard-filter by device eligibility.\n    platform = _platform()\n    eligible = [s for s in specs if s.is_available(platform)]\n    if len(eligible) == 1:\n        return eligible[0]\n    if not eligible:\n        raise ValueError(\n            f\"op {op!r} has no backend usable on device {platform.device.value!r} \"\n            f\"(registered: {[s.backend.value for s in specs]})\"\n        )\n    raise ValueError(\n        f\"op {op!r} has multiple backends usable on device \"\n        f\"{platform.device.value!r} ({[s.backend.value for s in eligible]}); \"\n        f\"pass backend=... to choose one\"\n    )\n\n\n@lru_cache(maxsize=None)\ndef _resolve(op: str, backend: Optional[KernelBackend]) -> Callable:\n    return select_kernel(op, backend=backend).load()\n\n\ndef get_kernel(op: str, backend: Optional[KernelBackend] = None) -> Callable:\n    \"\"\"Resolve ``op`` to a callable kernel and cache it.\n\n    This is what the public ``sglang.kernels.ops.*`` wrappers call. The first\n    call resolves and imports the backend; later calls hit the cache.\n    \"\"\"\n    return _resolve(op, backend)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/kernels/selector.py#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nspec = select_kernel(op)\n\n# after\nfrom sglang.kernels import Backend\nspec = select_kernel(op, backend=Backend.FLASHINFER)","handlingStrategy":"validation","validationCode":"from sglang.kernels.registry import registry\nfrom sglang.kernels.platform import _platform\n\np = _platform()\neligible = [s for s in registry.get(op, []) if s.is_available(p)]\nif len(eligible) > 1:\n    spec = select_kernel(op, backend=eligible[0].backend)  # or user-chosen\nelse:\n    spec = select_kernel(op)","typeGuard":null,"tryCatchPattern":"try:\n    spec = select_kernel(op)\nexcept ValueError as e:\n    if 'multiple backends' in str(e):\n        spec = select_kernel(op, backend=DEFAULT_BACKEND)\n    else:\n        raise","preventionTips":["Expose a backend config knob (env var) in multi-backend deployments.","Wrap resolution once in a helper with an explicit priority list."],"tags":["kernels","backend-selection","ambiguity","sglang"],"backgroundTag":"ambiguous-backend-selection","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}