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
- Call begin_load and wait for it to complete (poll status()) before generate().
- If a previous load failed, restart it and check its error before generating.
- 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
- Gate generate() on a loaded status in the client state machine.
- Treat this message as a reload signal, not an error to log loudly.
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
- Authorization flow is no longer active.
- A diffusion load is already in progress.
- load error: {p.get('error')}
- model load did not reach ready within {timeout_s}s
- load error: {p.get('error')}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/4a1a5aff91c6dfbb.
Report an issue: GitHub.