sgl-project/sglang · error · ValueError

invalid Rust extension build mode {mode!r}; expected auto, n

Error message

invalid Rust extension build mode {mode!r}; expected auto, never, or force

What it means

load_rust_extension(mode=...) only accepts 'auto', 'never', or 'force'. Any other mode string raises this ValueError; when mode is None the value comes from the SGLANG_RUST_BUILD_MODE env var. 'auto' uses bundled or cached builds, 'never' forbids invoking Cargo, 'force' rebuilds from source and replaces the cache entry.

Source

Thrown at python/sglang/srt/rust_extensions/loader.py:88

    cache_dir: Path | None = None,
    workspace: Path | None = None,
) -> ModuleType:
    """Import a PyO3 extension, compiling it locally when permitted and needed.

    The crate is discovered from the workspace under ``rust/``: the one whose
    Cargo manifest declares ``[package.metadata.sglang] python-module`` equal
    to ``python_module`` (the same metadata setup.py uses for wheel builds), so
    new crates need no registration here.

    ``auto`` prefers a module bundled in the installed wheel, then a cached
    local build, and finally Cargo. ``never`` permits the first two but never
    invokes Cargo. ``force`` rebuilds from source and replaces the cache entry.
    ``mode`` defaults to ``SGLANG_RUST_BUILD_MODE``.
    """
    if mode is None:
        mode = envs.SGLANG_RUST_BUILD_MODE.get()
    if mode not in ("auto", "never", "force"):
        raise ValueError(
            f"invalid Rust extension build mode {mode!r}; expected auto, never, or force"
        )

    if mode != "force":
        module = _import_bundled_extension(python_module)
        if module is not None:
            return module
    elif python_module in sys.modules:
        raise RuntimeError(
            f"cannot force-build {python_module} after it has been imported; "
            "start a new Python process"
        )

    if workspace is None:
        workspace = _RUST_WORKSPACE
    crate = _discover_crate(workspace, python_module)
    context = _build_context(crate)
    cache_root = _cache_root(cache_dir)

View on GitHub (pinned to 0132848349)

Solutions

  1. Set mode (or SGLANG_RUST_BUILD_MODE) to exactly auto, never, or force
  2. If you wanted rebuild-on-every-call semantics, that is 'force'
  3. Unset the env var to fall back to the default behavior instead of an invalid literal

Example fix

# before
SGLANG_RUST_BUILD_MODE=always python -m ...
# after
SGLANG_RUST_BUILD_MODE=force python -m ...
Defensive patterns

Strategy: validation

Validate before calling

assert mode in {"auto", "never", "force"}, f"bad build mode {mode!r}"

Type guard

def is_valid_build_mode(mode: str) -> bool:
    return mode in {"auto", "never", "force"}

Prevention

When it happens

Trigger: Passing mode="always", "True", or "" to load_rust_extension; setting SGLANG_RUST_BUILD_MODE to anything other than auto/never/force and calling the loader without an explicit mode.

Common situations: Copy-pasting build-mode values from other tools (e.g. 'always' instead of 'force'); typos in CI env vars; docs or examples referencing a removed mode name.

Related errors


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