{"record":{"id":"1a076907ec34f3e5","repo":"unslothai/unsloth","slug":"image-is-too-large-w-x-h-maximum-is-max-side","errorCode":null,"errorMessage":"Image is too large ({w}x{h}); maximum is {max_side}px per side.","messagePattern":"Image is too large \\((.+?)x(.+?)\\); maximum is (.+?)px per side\\.","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/diffusion.py","lineNumber":383,"sourceCode":"\n    from PIL import Image\n\n    raw = data.strip()\n    if raw.startswith(\"data:\"):\n        # data:[<mime>][;base64],<payload>\n        _, _, raw = raw.partition(\",\")\n    try:\n        blob = base64.b64decode(raw, validate = False)\n    except (binascii.Error, ValueError) as exc:\n        raise ValueError(f\"Invalid base64 image data: {exc}\") from exc\n    # Bound the decoded size: 4096px covers txt2img 2048, upscales and outpaint canvases.\n    max_side = 4096\n    try:\n        img = Image.open(io.BytesIO(blob))\n        # Reject from the header before img.load() so a huge-dimension file cannot spike memory.\n        w, h = img.size\n        if w > max_side or h > max_side:\n            raise ValueError(f\"Image is too large ({w}x{h}); maximum is {max_side}px per side.\")\n        img.load()\n    except ValueError:\n        raise  # the size guard's own message; don't wrap it as a decode error\n    except Exception as exc:  # noqa: BLE001 — surfaced as a 400 to the client\n        raise ValueError(f\"Could not decode image: {exc}\") from exc\n    return img.convert(mode)\n\n\ndef _snap_to_multiple(img: Any, multiple: int = 16) -> Any:\n    \"\"\"Resize a PIL image so both sides are multiples of ``multiple`` (rounded to nearest,\n    minimum one multiple), preserving content with a high-quality resample.\n\n    Image-conditioned pipelines (Z-Image / Qwen / FLUX: 8x VAE downsample + 2x patch) reject\n    sizes that are not divisible by 16. Rather than error on an odd-sized upload, snap it so\n    the workflow just works; rounding to nearest keeps the rescale minimal/accurate.\"\"\"\n    from PIL import Image\n\n    w, h = img.size","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/diffusion.py#L365-L401","documentation":"Raised by the image header check in the diffusion module: the decoded PIL image's width or height exceeds max_side (4096px), rejected before img.load() so a huge-dimension decompression bomb cannot spike memory. The 4096px bound deliberately covers txt2img 2048 plus upscale/outpaint canvases.","triggerScenarios":"Uploading a 6000×4000 photo for img2img; a PNG with large dimensions in its header (small file, huge decompressed size); upscaled scans; a canvas export at 8K.","commonSituations":"Phone/photo-library images at full resolution; print-quality scans; users assuming the server will downscale arbitrary inputs (it does for divisibility via _snap_to_multiple, not for the size cap).","solutions":["Downscale the image to ≤4096px on the longest side before uploading (any image editor or PIL thumbnail)","If you legitimately need bigger canvases, crop/outpaint in ≤4096 tiles","Do not bypass the guard by editing max_side — it exists to bound decode memory"],"exampleFix":"# client-side, before upload\nfrom PIL import Image\nimg = Image.open(\"photo.jpg\")\nimg.thumbnail((4096, 4096))\nimg.save(\"photo_small.jpg\")","handlingStrategy":"validation","validationCode":"MAX_SIDE = 4096\ndef within_size_limit(w: int, h: int) -> bool:\n    return w <= MAX_SIDE and h <= MAX_SIDE\n\ndef prepared_image(path: str):\n    from PIL import Image\n    img = Image.open(path)\n    if img.width > MAX_SIDE or img.height > MAX_SIDE:\n        img.thumbnail((MAX_SIDE, MAX_SIDE))\n    return img","typeGuard":null,"tryCatchPattern":"try:\n    img = parse_b64_image(data)\nexcept ValueError as e:\n    if \"too large\" in str(e):\n        return JSONResponse(status_code=422, content={\"detail\": str(e)})","preventionTips":["Thumbnail images to ≤4096px on the longest side before upload","Do not attempt to bypass the cap; it bounds decode memory server-side","Split oversized canvases into tiles for outpaint workflows"],"tags":["diffusion","image","size-limit","validation","client-error"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}