sgl-project/sglang · error · ImportError

{_METALLIB_NAME} not found next to the native Metal extensio

Error message

{_METALLIB_NAME} not found next to the native Metal extension at {_metallib_path}

What it means

This ImportError is raised at import time of sgl_kernel.metal when the default.metallib Metal shader library file is not found next to the compiled native extension (_metal). The Python wrapper verifies the .metallib artifact exists before calling _metal.register_library, because the Metal kernels cannot run without the precompiled shader library. If missing, the module silently sets _metal = None (guarded at call time), so the error surfaces later as a call-time failure on Metal platforms.

Source

Thrown at python/sglang/kernels/aot/python/sgl_kernel/metal.py:18

"""Python entry points for the sgl_kernel Metal extension."""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import mlx.core as mx

_METALLIB_NAME = "sgl_metal_kernels.metallib"

try:
    from . import _metal

    _metallib_path = Path(_metal.__file__).resolve().parent / _METALLIB_NAME
    if not _metallib_path.is_file():
        raise ImportError(
            f"{_METALLIB_NAME} not found next to the native Metal extension "
            f"at {_metallib_path}"
        )
    _metal.register_library(str(_metallib_path))
except ImportError as _exc:  # pragma: no cover - import guarded at call time
    _metal = None
    _IMPORT_ERROR: Exception | None = _exc
else:
    _IMPORT_ERROR = None

# Python wrappers for the compiled `_metal.*` entry points go below. Wrappers
# validate input shapes/dtypes and then invoke AOT C++ entry points. They do
# not force `mx.eval`, so MLX can keep these calls inside its lazy graph.


def rope_pool_fused(
    q: mx.array,
    k: mx.array,

View on GitHub (pinned to 0132848349)

Solutions

  1. Reinstall the wheel: pip install --force-reinstall sgl-kernel (use a macOS/Metal-enabled build)
  2. If building from source, run the Metal AOT build step that produces default.metallib and place it next to the _metal extension .so
  3. Verify the file exists: ls $(python -c "import sgl_kernel.metal as m; import os; print(os.path.dirname(m.__file__))")
  4. If on Linux/CUDA, this path is irrelevant — ensure you are not accidentally importing the metal module on a CUDA build

Example fix

# before: import fails silently, _metal is None
from sgl_kernel import metal
metal.rope_pool_fused(...)  # fails at call time

# after: guard at import time
from sgl_kernel import metal
if metal._metal is None:
    raise RuntimeError("Metal kernels unavailable; reinstall sgl-kernel for macOS")
Defensive patterns

Strategy: try-catch

Validate before calling

import importlib.util, pathlib
spec = importlib.util.find_spec("sgl_kernel._metal")
metallib_ok = spec is not None and (pathlib.Path(spec.origin).parent / "default.metallib").is_file()

Type guard

def metal_available() -> bool:
    try:
        from sgl_kernel import metal
        return metal._metal is not None
    except Exception:
        return False

Try / catch

try:
    from sgl_kernel import metal
except ImportError:
    metal = None
if metal is None or metal._metal is None:
    raise RuntimeError("Metal kernels unavailable; reinstall macOS sgl-kernel build")

Prevention

When it happens

Trigger: Importing sgl_kernel.metal on macOS/Metal builds where the wheel or AOT build did not package default.metallib next to the _metal native extension; broken pip install; building from source without running the Metal AOT kernel build step; manually copying the extension without its .metallib.

Common situations: Installing an sgl-kernel wheel built without Metal support; upgrading sgl-kernel to a version with a changed packaging layout; running on non-Apple hardware where Metal artifacts are absent; source builds where CMAKE/BuildMetal step was skipped.

Related errors


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