{"record":{"id":"00705f28d569920d","repo":"unslothai/unsloth","slug":"sd-cli-binary-is-present-but-not-runnable","errorCode":null,"errorMessage":"sd-cli binary is present but not runnable.","messagePattern":"sd-cli binary is present but not runnable\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/inference/sd_cpp_backend.py","lineNumber":1335,"sourceCode":"                    mode, server_binary, engine = \"oneshot\", None, fallback\n            # The accelerator the managed tree held when THIS binary was chosen, taken where the\n            # choice is made rather than sampled again later. The asset download below runs for\n            # minutes with no claim on the tree, and an install that lands in that window replaces\n            # sd-server in place: same path, still runnable, a different build. \"It exists and it\n            # runs\" is therefore not evidence that it is the build this load resolved its device\n            # and offload policy for, so the answer is re-asked under the reader claim.\n            server_accelerator = _installed_accelerator_of(server_binary)\n            # The same pin for the one-shot CLI, and for the same reason. Sampling it only at\n            # state construction, after the download, would record whatever an install left in\n            # the tree in that window and the first generation -- which re-reads the tree and\n            # compares -- would then agree with the replacement, so the check that exists to\n            # notice a swap could never fire for one that landed during the download.\n            engine_accelerator = _installed_accelerator_of(getattr(engine, \"binary\", None))\n            if mode == \"oneshot\":\n                # version() is None when a present binary can't run; fail now, not on the first generation.\n                assert engine is not None\n                if engine.version() is None:\n                    raise RuntimeError(\"sd-cli binary is present but not runnable.\")\n\n            # Swap ONCE so the size probe and the download agree: sizes come from paths-info, which\n            # -- unlike model_info -- 401s anonymously on a gated repo, so probing the upstream\n            # drops the VAE from the progress total the mirror then pulls.\n            inner_dim = self._flux2_inner_dim(repo_id, gguf_filename, fam, hf_token)\n            specs = self._asset_specs(repo_id, gguf_filename, fam, inner_dim)\n            fetch_repo = _fetch_repo_map(specs, hf_token)\n            assets = [(fetch_repo[repo], fn, kind) for repo, fn, kind in specs]\n            # begin_load could only guess the encoder repos (it may not have had the header yet);\n            # now they are known, so publish them before a single byte is fetched. Otherwise\n            # delete-cached would happily remove a companion this load is about to write into.\n            with self._lock:\n                if self._load_token == _load_token and self._loading is not None:\n                    self._loading.asset_repos = tuple(\n                        dict.fromkeys(r for r, _f, kind in specs if kind != \"diffusion_model\")\n                    )\n            # And record them, from the SAME post-probe specs. begin_load records what it can, but\n            # it resolves the header offline, so a remote or renamed FLUX.2-klein 9B checkpoint","sourceCodeStart":1317,"sourceCodeEnd":1353,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/sd_cpp_backend.py#L1317-L1353","documentation":"RuntimeError on the one-shot load path: mode resolved to 'oneshot' but engine.version() is None, i.e. the sd-cli binary is present yet cannot execute. Failing at load time (rather than the first generation) gives an early, clear signal.","triggerScenarios":"Load with mode=='oneshot' (older/custom build without the server target, or an injected engine) where the CLI binary is corrupt or its runtime is broken.","commonSituations":"Partial download of the managed CLI bundle; broken dynamic-library environment; architecture mismatch; file permissions after moving an install.","solutions":["Execute the binary directly to surface the underlying exec failure.","Reinstall the managed binary (delete the tree / allow install) or point SD_CLI_PATH at a working build.","Fix the runtime environment (ldd-reported missing libs, exec permissions)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import subprocess\n\ndef cli_runs(binary: str) -> bool:\n    try:\n        return subprocess.run([binary, '--version'], capture_output=True, timeout=20).returncode == 0\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    backend.begin_load(repo_id=r, gguf_filename=f)\nexcept RuntimeError as e:\n    if 'sd-cli binary is present but not runnable' in str(e):\n        reinstall_or_repoint_cli()\n        backend.begin_load(repo_id=r, gguf_filename=f)\n    raise","preventionTips":["Verify the sd-cli binary executes on the target host before relying on one-shot mode.","Reinstall the managed bundle after OS upgrades that change dynamic libraries."],"tags":["binary-validation","installation","sd-cpp","environment"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}