{"record":{"id":"0347dad50fd27abe","repo":"unslothai/unsloth","slug":"exc","errorCode":null,"errorMessage":"{exc}","messagePattern":"\\{exc\\}","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/diffusion.py","lineNumber":5449,"sourceCode":"                            transformer_quant = state.transformer_quant,\n                        ):\n                            raise ValueError(\n                                \"ControlNet is not supported for this model/quantisation on the \"\n                                \"diffusers engine (needs a bf16 or bnb-4bit load of a family with a \"\n                                \"ControlNet pipeline; not GGUF-via-diffusers or torchao fp8/int8).\"\n                            )\n                        # Decode + preprocess the control image FIRST so a bad image 400s before any CN download, at the OUTPUT size.\n                        src = decode_b64_image(cn_image_b64, mode = \"RGB\")\n                        control_pil = diffusion_controlnet.preprocess_control(src, cn_type).resize(\n                            (width, height), Image.LANCZOS\n                        )\n                        try:\n                            resolved_cn = diffusion_controlnet.resolve_controlnet(\n                                cn_id, family = state.family.name\n                            )\n                        except FileNotFoundError as exc:\n                            # An unknown CN id -> 400, not 500 (the route maps ValueError).\n                            raise ValueError(str(exc)) from exc\n                        pipe = self._controlnet_pipe(state, resolved_cn, cancel)\n                        workflow = \"controlnet\"\n                        cn_scale, cn_gstart, cn_gend = cn_strength, cn_gs, cn_ge\n                        # Flux Union CN selects its head by an integer control_mode; map the type.\n                        cn_mode = diffusion_controlnet.union_control_mode(cn_id, cn_type)\n                # A prompt LIST batches plain text-to-image only: conditioned workflows take one image per call and a silent broadcast would pair every prompt with it.\n                if uniform_prompt(jobs) is None and workflow != \"txt2img\":\n                    raise ValueError(\n                        \"A prompts list is supported for plain text-to-image only; the \"\n                        f\"{workflow} workflow takes one prompt per call (seed lists still work).\"\n                    )\n                # Snap odd-sized inputs (and the mask) to a multiple of 16 where the OUTPUT size comes from the input image.\n                if init_pil is not None and workflow in (\"img2img\", \"inpaint\", \"edit\"):\n                    # img2img/inpaint take output size from the upload, so bound the longest side to 2048 (a phone photo would OOM).\n                    if workflow == \"img2img\":\n                        # ...and bound Transform by the REQUESTED size too, so the Resolution\n                        # control caps the output instead of being inert. img2img only: an\n                        # inpaint payload is the canvas the mask was painted against (Extend","sourceCodeStart":5431,"sourceCodeEnd":5467,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/diffusion.py#L5431-L5467","documentation":"A FileNotFoundError from resolve_controlnet (unknown ControlNet id not in the catalog) is re-raised as ValueError with the original message. The comment in source makes the intent explicit: the route maps ValueError to HTTP 400, so an unknown CN id surfaces as a client error rather than a bare 500.","triggerScenarios":"Passing a controlnet tuple whose id does not match any curated catalog entry or known repo id — e.g. a typo'd id, a repo that was never registered, or an entry removed from the catalog.","commonSituations":"Hand-writing API payloads with a ControlNet repo id from memory; catalogs drifting between versions so a previously valid id disappears; stale UI state referencing a deleted curated entry.","solutions":["Use a ControlNet id from the current catalog (list available ControlNets via the app's catalog/registry endpoint or diffusion_controlnet catalog helpers).","Check for typos in the repo id / spec id — full repo ids must match a curated entry exactly.","If the CN was local ('source: local'), confirm it is still present on disk and re-registered."],"exampleFix":"# before\ncontrolnet=(\"xinsir-controlnet-sdxl-canny\", img, \"canny\", 0.8, 0.0, 1.0)  # typo'd id\n# after\ncontrolnet=(\"xinsir-controlnet-v1.1-sdxl-canny\", img, \"canny\", 0.8, 0.0, 1.0)  # exact catalog id","handlingStrategy":"validation","validationCode":"from core.inference.diffusion_controlnet import _catalog_by_id  # or a public list endpoint\n\ndef valid_cn_id(spec_id: str) -> bool:\n    return spec_id in _catalog_by_id() or any(\n        e.repo_id == spec_id for e in getattr(__import__(\"core.inference.diffusion_controlnet\", fromlist=[\"_CURATED\"]), \"_CURATED\")\n    )","typeGuard":null,"tryCatchPattern":"try:\n    out = engine.generate(prompt=p, controlnet=(cn_id, img, t, s, gs, ge))\nexcept ValueError as e:\n    if \"ControlNet\" in str(e) and \"no longer present\" not in str(e):\n        refresh_cn_catalog_and_repick()  # 400-class: fix the id, don't retry the same one\n    else:\n        raise","preventionTips":["Populate CN pickers from the live catalog, not hardcoded ids.","Re-validate stored CN ids after upgrading the app (catalogs drift between versions)."],"tags":["diffusion","controlnet","catalog","not-found","http-400"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}