unslothai/unsloth · error · RuntimeError

No diffusion model is loaded.

Error message

No diffusion model is loaded.

What it means

RuntimeError (DIFFUSION_NOT_LOADED_MSG) raised under the generate lock when self._state is None: generate() was called before any model finished loading, or after unload(). The backend distinguishes this from a 500 so the client gets the reload path.

Source

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

                "Batched prompt/seed lists are not supported on the native sd.cpp engine "
                "(it renders serially); run on a GPU (diffusers) for batched generation, "
                "or use batch_size for a serial native batch."
            )
        # strength 0/None disables ControlNet (matches diffusers), so no-op it rather than 400.
        if controlnet is not None and controlnet[3] in (None, 0, 0.0):
            controlnet = None
        if controlnet is not None:
            raise ValueError(
                "ControlNet is not yet supported on the native sd.cpp engine; run on a GPU "
                "(diffusers) for ControlNet conditioning."
            )

        cancel = threading.Event()
        with self._generate_lock:
            with self._lock:
                state = self._state
                if state is None:
                    raise RuntimeError(DIFFUSION_NOT_LOADED_MSG)
                # A resident server can exit while idle; drop stale state and report not-loaded so the client gets the reload path, not a 500.
                if (
                    state.mode == "server"
                    and state.server is not None
                    and not state.server.is_alive()
                ):
                    self._state = None
                    raise RuntimeError(DIFFUSION_NOT_LOADED_MSG)
                self._active_generate_cancel = cancel
                # Publish an active (step 0) state before the slow pre-generate setup so a reload probe does not read idle while this holds _generate_lock.
                self._gen = _SdGen(total_steps = int(steps))
            try:
                if seed is None:
                    seed = int.from_bytes(os.urandom(6), "big") & ((1 << 53) - 1)
                else:
                    seed = int(seed)
                cfg_scale, flux_guidance = _map_guidance(state.family, guidance)
                # Resolve selected LoRAs up front (a bad id gives a clear 400). Drop weight-0 rows BEFORE the support gate so an only-disabled request stays a no-op.

View on GitHub (pinned to 203007d190)

Solutions

  1. Call begin_load and wait for it to complete (poll status()) before generate().
  2. If a previous load failed, restart it and check its error before generating.
  3. After unload(), load a model again before generating.

Example fix

# before
backend.generate(prompt='a cat')  # nothing loaded

# after
backend.begin_load(repo_id=..., gguf_filename=...)
wait_until_loaded(backend)
backend.generate(prompt='a cat')
Defensive patterns

Strategy: validation

Validate before calling

status = backend.status()
if status.get('state') is None or not status.get('loaded'):
    wait_until_loaded(backend)  # or issue begin_load first

Try / catch

try:
    result = backend.generate(prompt=p)
except RuntimeError as e:
    if 'No diffusion model is loaded' in str(e):
        wait_until_loaded(backend)
        result = backend.generate(prompt=p)
    else:
        raise

Prevention

When it happens

Trigger: generate() before begin_load completes; generate() after unload() or after a failed load left no state.

Common situations: UI firing generation before the load indicator clears; restarts that drop in-flight loads; calling generate right after a cancel that tore down state.

Related errors


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