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

  1. Read the embedded last-12-lines tail — it names the actual failure; act on that, not on the exit code.
  2. Exit code 139/134 (segv/abort) with memory lines: reduce resolution/steps, enable offload, or use a smaller quant.
  3. Model-load errors: verify the GGUF checksum / re-download, and confirm the CLI build supports the model architecture.
  4. 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

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


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