{"record":{"id":"a42207454dce9ab3","repo":"unslothai/unsloth","slug":"mask-image-requires-an-input-image-init-image","errorCode":null,"errorMessage":"mask_image requires an input image (init_image).","messagePattern":"mask_image requires an input image \\(init_image\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/diffusion.py","lineNumber":5344,"sourceCode":"                    except Exception as exc:  # noqa: BLE001 — speed is best-effort\n                        logger.warning(\n                            \"diffusion.speed: deferred engagement failed, staying eager: %s\",\n                            exc,\n                        )\n\n                # Apply/adjust LoRA before picking the workflow pipe; from_pipe pipes share the transformer.\n                self._apply_loras(state, loras, cancel)\n\n                # Select the workflow pipe: txt2img uses the loaded pipe; img2img/inpaint reuse its modules via from_pipe.\n                pipe = state.pipe\n                init_pil = mask_pil = None\n                control_pil = None\n                cn_scale = cn_gstart = cn_gend = cn_mode = None\n                ref_extra: list = []\n                # Validate dependencies up front: mask/upscale/reference need an input image, and reference needs a supporting family.\n                if init_image is None:\n                    if mask_image is not None:\n                        raise ValueError(\"mask_image requires an input image (init_image).\")\n                    if upscale is not None and upscale > 1.0:\n                        raise ValueError(\"upscale requires an input image (init_image).\")\n                    if reference_images:\n                        raise ValueError(\"reference_images require an input image (init_image).\")\n                if reference_images and not getattr(state.family, \"reference\", False):\n                    raise ValueError(\n                        f\"Reference images are not supported for the '{state.family.name}' \"\n                        \"model family.\"\n                    )\n                if getattr(state.family, \"edit\", False):\n                    # Instruction editing: the loaded pipe IS the edit pipeline and always needs an input image; the prompt is the instruction.\n                    if init_image is None:\n                        raise ValueError(\n                            f\"{state.family.name} is an image-editing model: provide an input image.\"\n                        )\n                    if mask_image is not None:\n                        # The edit family has no inpaint pipeline; a mask would be silently dropped.\n                        raise ValueError(","sourceCodeStart":5326,"sourceCodeEnd":5362,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/diffusion.py#L5326-L5362","documentation":"Up-front dependency validation in generate(): a `mask_image` (for inpainting) only makes sense with an `init_image` to mask. The code validates all input-image dependencies before touching device objects or building workflow pipes, raising a clean ValueError when init_image is None but mask_image was supplied. Failing early avoids loading an inpaint pipeline for an impossible request.","triggerScenarios":"Calling generate() with `mask_image` set (base64 control/mask input) while `init_image` is None; the first branch of the `if init_image is None:` validation block fires.","commonSituations":"Frontend sending the mask from a canvas but dropping the init image on serialization; clients copying an inpaint payload and deleting the init_image field; partial multipart uploads where the image part fails but the mask part arrives.","solutions":["Include init_image whenever mask_image is provided.","Validate the request client-side: assert init_image is present if mask_image is.","If pure txt2img was intended, remove mask_image from the call."],"exampleFix":"# before\ndiffusion.generate(prompt=\"...\", mask_image=mask_b64)  # no init_image\n# after\ndiffusion.generate(prompt=\"...\", init_image=img_b64, mask_image=mask_b64)","handlingStrategy":"validation","validationCode":"if mask_image is not None and init_image is None:\n    raise ValueError(\"mask_image requires init_image\")  # fail client-side, before the API\ndiffusion.generate(prompt=p, init_image=init_image, mask_image=mask_image)","typeGuard":"def valid_mask_request(init_image, mask_image) -> bool:\n    \"\"\"A mask may only accompany an init image.\"\"\"\n    return mask_image is None or init_image is not None","tryCatchPattern":"try:\n    diffusion.generate(**params)\nexcept ValueError as e:\n    if \"mask_image requires an input image\" in str(e):\n        params.pop(\"mask_image\")\n        return diffusion.generate(**params)  # degrade to plain generation\n    raise","preventionTips":["Assert pairwise request dependencies (mask/upscale/reference all need init_image) in client schemas.","Disable inpaint controls in the UI until a base image is attached.","Test multipart payloads where individual image fields are omitted."],"tags":["diffusion","inpainting","validation","request-payload"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}