unslothai/unsloth · error · RuntimeError

sd-server binary is present but not runnable.

Error message

sd-server binary is present but not runnable.

What it means

RuntimeError on the load path: a persistent sd-server binary exists at the expected path, but when the engine tried to resolve a fallback sd-cli engine its version() came back None (or resolution raised), meaning the present binary cannot actually run. The load aborts now rather than failing on first generation.

Source

Thrown at studio/backend/core/inference/sd_cpp_backend.py:1316

            if mode == "server":
                # Probe the server binary before the pull: a present-but-unrunnable build would download everything then fail.
                assert server_binary is not None
                if not _server_binary_runnable(server_binary):
                    logger.warning(
                        "sd-server at %s is present but not runnable; trying one-shot sd-cli.",
                        server_binary,
                    )
                    # Resolve ONCE and keep it: two calls can answer with two different
                    # binaries if an install lands between them, and the state below reads the
                    # accelerator off whichever object it ends up holding.
                    fallback: Optional[SdCppEngine] = None
                    try:
                        fallback = self._resolve_engine()
                        usable = fallback.version() is not None
                    except Exception:  # noqa: BLE001
                        usable = False
                    if not usable or fallback is None:
                        raise RuntimeError("sd-server binary is present but not runnable.")
                    mode, server_binary, engine = "oneshot", None, fallback
            # The accelerator the managed tree held when THIS binary was chosen, taken where the
            # choice is made rather than sampled again later. The asset download below runs for
            # minutes with no claim on the tree, and an install that lands in that window replaces
            # sd-server in place: same path, still runnable, a different build. "It exists and it
            # runs" is therefore not evidence that it is the build this load resolved its device
            # and offload policy for, so the answer is re-asked under the reader claim.
            server_accelerator = _installed_accelerator_of(server_binary)
            # The same pin for the one-shot CLI, and for the same reason. Sampling it only at
            # state construction, after the download, would record whatever an install left in
            # the tree in that window and the first generation -- which re-reads the tree and
            # compares -- would then agree with the replacement, so the check that exists to
            # notice a swap could never fire for one that landed during the download.
            engine_accelerator = _installed_accelerator_of(getattr(engine, "binary", None))
            if mode == "oneshot":
                # version() is None when a present binary can't run; fail now, not on the first generation.
                assert engine is not None
                if engine.version() is None:

View on GitHub (pinned to 203007d190)

Solutions

  1. Run the binary directly (`<path>/sd-server --version` and `sd-cli --version`) to see the real exec error (missing .so, exec format error).
  2. Delete the managed binary tree and let the backend reinstall a fresh copy.
  3. Install missing runtime libraries reported by ldd, or point SD_CLI_PATH at a known-good build.
  4. Retrying the load after the fix re-resolves device and binaries from scratch.
Defensive patterns

Strategy: retry

Validate before calling

import subprocess

def binary_runs(path: str) -> bool:
    try:
        return subprocess.run([path, '--version'], capture_output=True, timeout=20).returncode == 0
    except Exception:
        return False

Try / catch

try:
    backend.begin_load(repo_id=r, gguf_filename=f)
except RuntimeError as e:
    if 'not runnable' in str(e):
        reinstall_managed_binary()
        backend.begin_load(repo_id=r, gguf_filename=f)  # retry re-resolves from scratch
    raise

Prevention

When it happens

Trigger: Load in server mode finds the server unusable, falls back to one-shot, and the fallback binary also fails to execute (version() is None) — corrupted binary, missing dynamic libraries, wrong architecture.

Common situations: Truncated/partially downloaded managed binary; system library mismatch (libstdc++, CUDA runtime) after an OS upgrade; a binary copied from another architecture.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/93a81be1b00e130e. Report an issue: GitHub.