unslothai/unsloth · error · RuntimeError
sd-cli exited {ret}. Last output: {"\n".join(tail[-12:])}
Error message
sd-cli exited {ret}. Last output:
{"\n".join(tail[-12:])} What it means
The sd-cli subprocess exited with a non-zero return code. The message embeds the exit status and the last 12 stdout/stderr lines captured by the reader thread, which is the primary diagnostic: it usually shows the real cause (model load failure, OOM, unsupported GGUF feature, bad argument). The process is terminated and its pid untracked in the finally block, so no zombie remains.
Source
Thrown at studio/backend/core/inference/sd_cpp_engine.py:822
if proc.poll() is not None:
break
continue
tail.append(line)
if len(tail) > 40:
tail.pop(0)
if on_log is not None:
on_log(line)
ret = proc.wait(timeout = 5.0)
finally:
if proc.poll() is None:
_terminate(proc)
# Only once it has actually exited: a pid still running has to stay
# recorded, or the next startup has no handle on it.
if proc.poll() is not None:
forget_pid(proc.pid)
if ret != 0:
raise RuntimeError(f"sd-cli exited {ret}. Last output:\n" + "\n".join(tail[-12:]))
if not out.is_file():
raise RuntimeError(
f"sd-cli reported success but no image at {out}. Last output:\n"
+ "\n".join(tail[-12:])
)
logger.info("sd-cli run ok in %.1fs -> %s", time.time() - t0, out)
return out
# ── engine routing ──────────────────────────────────────────────────────────
ENGINE_DIFFUSERS = "diffusers"
ENGINE_SD_CPP = "sd_cpp"
# Backends diffusers serves well with GPU acceleration; everything else is native-engine territory.
_GPU_BACKENDS = frozenset({"cuda", "rocm", "xpu"})
View on GitHub (pinned to 203007d190)
Solutions
- Read the embedded last-12-lines tail — it names the actual failure; act on that, not on the exit code.
- Exit code 139/134 (segv/abort) with memory lines: reduce resolution/steps, enable offload, or use a smaller quant.
- Model-load errors: verify the GGUF checksum / re-download, and confirm the CLI build supports the model architecture.
- Keep the sd-cli build in sync with the backend version (rebuild or `unsloth studio update`).
Defensive patterns
Strategy: try-catch
Try / catch
try:
engine.generate(...)
except RuntimeError as e:
msg = str(e)
if "exited" in msg:
tail = msg.split("Last output:", 1)[-1]
log_for_triage(tail) # act on the real cause in the tail
raise Prevention
- Always log the embedded tail — it contains the actual CLI error.
- Validate model files (size/checksum) before handing them to the CLI.
- Match CLI build features (CUDA/FA) to the model's requirements before running.
When it happens
Trigger: Any sd-cli run that fails internally: corrupt or unsupported model files, out-of-memory during load or sampling, invalid prompt/param encodings, or missing accelerator drivers.
Common situations: Model quantization not supported by the installed CLI version; GPU OOM on large models; truncated GGUF download; CLI built without the backend the model needs (e.g. FlashAttention, CUDA).
Related errors
- sd-cli timed out after {timeout}s
- sd-cli reported success but no image at {out}. Last output:
- sd-server returned {len(blobs)} of {count} requested images
- The stable-diffusion.cpp binary was replaced by an install f
- sd-cli (stable-diffusion.cpp) binary not found. Build it or
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/f1601ebde6fb1abb.
Report an issue: GitHub.