{"record":{"id":"5ca92397868678b7","repo":"unslothai/unsloth","slug":"no-diffusion-model-is-loaded","errorCode":null,"errorMessage":"No diffusion model is loaded.","messagePattern":"No diffusion model is loaded\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"studio/backend/core/inference/diffusion.py","lineNumber":5291,"sourceCode":"        reference_images: Optional[list[str]] = None,\n        # LoRA (id, weight) pairs; loaded non-fused and activated for this generation. None/empty clears.\n        loras: Optional[list[tuple[str, float]]] = None,\n        # ControlNet (id, control_image_b64, control_type, strength, guidance_start, guidance_end). None = off.\n        controlnet: Optional[tuple[str, str, str, float, float, float]] = None,\n    ) -> dict[str, Any]:\n        import torch\n        from PIL import Image\n\n        # Per-generation cancel Event that unload()/a superseding load set (under _lock) to abort just this denoise.\n        cancel = threading.Event()\n        with self._generate_lock:\n            with self._lock:\n                # A teardown is waiting for this lock and Python locks are not FIFO, so refuse rather than start a denoise on a pipeline that is already being torn down.\n                if self._teardown_waiters:\n                    raise RuntimeError(DIFFUSION_CANCELLED_MSG)\n                state = self._state\n                if state is None:\n                    raise RuntimeError(DIFFUSION_NOT_LOADED_MSG)\n                # Register under _lock so unload()/a load can signal THIS generation.\n                self._active_generate_cancel = cancel\n                # Publish an active (step 0) state before the slow pre-denoise setup so a reload mount probe does not read idle.\n                self._gen = _GenState(total_steps = steps)\n            try:\n                # FIRST, before any device object exists. This worker is not the thread that loaded\n                # the pipeline, so until it is pinned the un-indexed state.device below -- and the\n                # ControlNet placement further down -- resolve to its own default card while the\n                # weights sit on the selected one.\n                self._state_device_target(state)\n                # The local `state` ref keeps the pipe alive even if unload() nulls _state. Resolve the per-image (prompt, seed) jobs\n                # up front: N prompts, one prompt x N seeds, or one prompt deriving base..base+batch_size-1 (as the native engine does).\n                jobs, seed = resolve_batch_jobs(\n                    prompt = prompt,\n                    prompts = prompts,\n                    seed = seed,\n                    seeds = seeds,\n                    batch_size = batch_size,","sourceCodeStart":5273,"sourceCodeEnd":5309,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/diffusion.py#L5273-L5309","documentation":"generate() precondition: `self._state` is None, meaning no diffusion model is currently loaded (never loaded, or unloaded). The local `state` reference is how the rest of generate() survives concurrent unloads, but if it is None at entry there is nothing to run, so RuntimeError(DIFFUSION_NOT_LOADED_MSG) raises immediately under the lock.","triggerScenarios":"Calling generate() before any successful load(), after unload(), or after a failed load left `_state` null. The check `state = self._state; if state is None: raise` fires under `_lock`.","commonSituations":"API clients firing a generation request before the load request completes; UI allowing generate while the model slot is empty; a previous load failed (OOM, bad repo) and the client did not check the result.","solutions":["Call load() and wait for success before generate().","Check the loaded-model status endpoint before dispatching generation work.","If a previous load failed, address its error (VRAM, repo access) first."],"exampleFix":"# before\ndiffusion.generate(prompt=\"a cat\")  # nothing loaded\n# after\ndiffusion.load(model=repo)\ndiffusion.generate(prompt=\"a cat\")","handlingStrategy":"validation","validationCode":"if diffusion.loaded_model() is None:  # status endpoint / loaded-state probe\n    await diffusion.load(model=repo)\nresult = diffusion.generate(prompt=p)","typeGuard":"def is_loaded(diffusion) -> bool:\n    \"\"\"A pipeline state is resident and generate() can proceed.\"\"\"\n    return diffusion.loaded_model() is not None","tryCatchPattern":"try:\n    diffusion.generate(prompt=p)\nexcept RuntimeError as e:\n    if \"No diffusion model is loaded\" in str(e):\n        await diffusion.load(model=repo)\n        return diffusion.generate(prompt=p)\n    raise","preventionTips":["Await load completion before dispatching generations.","Handle failed loads explicitly -- a null state persists until the next successful load.","Expose loaded-model status in health checks for schedulers."],"tags":["diffusion","lifecycle","validation","model-loading"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}