{"record":{"id":"61704869fe1d78d5","repo":"unslothai/unsloth","slug":"must-be-a-multiple-of-16","errorCode":null,"errorMessage":"must be a multiple of 16","messagePattern":"must be a multiple of 16","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"studio/backend/models/inference.py","lineNumber":3072,"sourceCode":"                seen.add(spec.id)\n        return value\n\n    @field_validator(\"reference_images\")\n    @classmethod\n    def _bounded_reference_items(cls, value: Optional[list[str]]) -> Optional[list[str]]:\n        # Each reference is a base64 image; bound its length like init_image so several cannot buffer a multi-GB payload.\n        if value is not None:\n            for item in value:\n                if len(item) > 32 * 1024 * 1024:\n                    raise ValueError(\"each reference image must be at most 32 MiB (base64)\")\n        return value\n\n    @field_validator(\"width\", \"height\")\n    @classmethod\n    def _multiple_of_16(cls, value: int) -> int:\n        # Z-Image requires dimensions divisible by 16 (8x VAE downsample + 2x patch); non-multiples crash deep in the pipeline.\n        if value % 16 != 0:\n            raise ValueError(\"must be a multiple of 16\")\n        return value\n\n    @model_validator(mode = \"after\")\n    def _batch_seeds_json_safe(self) -> \"DiffusionGenerateRequest\":\n        # A batch derives seeds as seed..seed+batch_size-1, so a derived top-of-batch seed can exceed the 2**53-1 JSON-safe cap.\n        if self.seed is not None and self.seed + self.batch_size - 1 > 2**53 - 1:\n            raise ValueError(\n                \"seed + batch_size - 1 must not exceed 2**53 - 1 so every per-image seed \"\n                \"stays JSON-safe (lower the seed or the batch_size)\"\n            )\n        return self\n\n\nclass GalleryImage(BaseModel):\n    \"\"\"A persisted image's full generation recipe (embedded in the PNG too).\"\"\"\n\n    id: str = Field(..., description = \"Stable id (the on-disk filename stem)\")\n    url: str = Field(..., description = \"Relative URL to fetch the PNG bytes\")","sourceCodeStart":3054,"sourceCodeEnd":3090,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/models/inference.py#L3054-L3090","documentation":"Raised by the width/height field_validator on DiffusionGenerateRequest when either dimension is not divisible by 16. Z-Image requires dimensions divisible by 16 (8x VAE downsample + 2x patch); non-multiples crash deep in the pipeline, so they are rejected up front with a clean 422.","triggerScenarios":"POST /generate with width: 1000 or height: 1023 (the field bounds are 256..2048 but only multiples of 16 in that range are valid).","commonSituations":"UIs with free-form pixel inputs or sliders with step 1; deriving dimensions from aspect-ratio math (e.g. 1.5:1 of 1024 -> 1536 is fine but 1365 is not); client-side presets authored with off-by-a-few values.","solutions":["Round dimensions to the nearest multiple of 16 client-side (see validationCode).","Set slider/input step to 16 in the UI.","When computing from aspect ratio, quantize both dimensions after the ratio math."],"exampleFix":"# before\nw, h = 1024, round(1024 * 1.5)  # 1536 ok, but 1365 from other ratios fails\n\n# after\ndef to_multiple_of_16(v): return max(256, min(2048, round(v / 16) * 16))\nw, h = to_multiple_of_16(1024), to_multiple_of_16(1024 * 1.5)","handlingStrategy":"validation","validationCode":"def quantize_dim(v: int) -> int:\n    return max(256, min(2048, round(v / 16) * 16))","typeGuard":"def is_valid_dimension(v: int) -> bool:\n    return 256 <= v <= 2048 and v % 16 == 0","tryCatchPattern":null,"preventionTips":["Give dimension inputs/sliders step=16 within 256..2048","Quantize after aspect-ratio math, not before","Use multiples-of-16 presets as the only selectable sizes"],"tags":["pydantic","validation","diffusion","image-dimensions","alignment"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}