{"record":{"id":"a2170212c0cabc0c","repo":"odysseus-dev/odysseus","slug":"lama-mi-gan-inpainting-requires-an-image-mask-u","errorCode":null,"errorMessage":"LaMa / MI-GAN inpainting requires an image mask. Use the editor inpaint/object-removal tool so Odysseus can send the mask.","messagePattern":"LaMa / MI-GAN inpainting requires an image mask\\. Use the editor inpaint/object-removal tool so Odysseus can send the mask\\.","errorType":"http","errorClass":"HTTPException","httpStatus":422,"severity":"error","filePath":"scripts/mlx_image_server.py","lineNumber":234,"sourceCode":"    if not bridge:\n        raise _unsupported_swift_mlx_runtime(model)\n    with tempfile.TemporaryDirectory(prefix=\"odysseus-ddcolor-\") as td:\n        inp = Path(td) / \"input.png\"\n        _write_bridge_input_image(image_raw, inp)\n        weights = _weights_path(model)\n        tier = \"tiny\" if \"tiny\" in model.lower() else \"large\"\n        _run_bridge([\n            bridge,\n            \"--model\", str(weights),\n            \"--image\", str(inp),\n            \"--output\", str(out_path),\n            \"--tier\", tier,\n        ])\n\n\ndef _run_inpaint_bridge(model: str, image_raw: bytes, mask_raw: bytes | None, out_path: Path) -> None:\n    if not mask_raw:\n        raise HTTPException(\n            422,\n            \"LaMa / MI-GAN inpainting requires an image mask. Use the editor inpaint/object-removal tool so Odysseus can send the mask.\",\n        )\n    bridge = _resolve_bridge([\"odysseus-mlx-inpaint\", \"mlx-lama-serve\"])\n    if not bridge:\n        raise _unsupported_swift_mlx_runtime(model)\n    with tempfile.TemporaryDirectory(prefix=\"odysseus-mlx-inpaint-\") as td:\n        inp = Path(td) / \"input.png\"\n        mask = Path(td) / \"mask.png\"\n        _write_bridge_input_image(image_raw, inp)\n        _write_bridge_mask(mask_raw, mask)\n        weights = _weights_path(model)\n        mode = \"fast\" if (\"mi-gan\" in model.lower() or \"migan\" in model.lower()) else \"best\"\n        _run_bridge([\n            bridge,\n            \"--model\", str(weights),\n            \"--image\", str(inp),\n            \"--mask\", str(mask),","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/scripts/mlx_image_server.py#L216-L252","documentation":"Raised by _run_inpaint_bridge in scripts/mlx_image_server.py with HTTP 422 when the LaMa / MI-GAN inpainting path is invoked with no mask bytes. These models are pure inpainters: unlike diffusion img2img they cannot operate on the whole image, so the server requires the multipart 'mask' upload.","triggerScenarios":"POST /v1/images/edits with an 'image' but no 'mask' field (or an empty mask file) while serving a LaMa/MI-GAN model. Also harmonize requests where body_mask and mask are both null for a LaMa model.","commonSituations":"Client built for diffusion edit endpoints that treat masks as optional; generic OpenAI SDK images.edit call without mask; UI tool that only sends the image for 'enhance' style operations; mask field sent but empty because the user drew nothing.","solutions":["Send a mask: multipart 'mask' file (RGBA PNG with transparent = regenerate, or L-mode) marking the region to inpaint","Use an editor tool that produces and uploads the mask (the message points at Odysseus's inpaint/object-removal tool)","For whole-image restoration/colorize instead of region edit, switch to a DDColor model which needs no mask"],"exampleFix":"# before\nfiles = {'image': open('photo.png','rb'), 'prompt': 'remove person'}\n# after\nfiles = {'image': open('photo.png','rb'), 'mask': open('person-mask.png','rb'), 'prompt': 'remove person'}","handlingStrategy":"validation","validationCode":"def validate_edit_request(image: bytes, mask: bytes | None, model: str) -> None:\n    assert image, 'image required'\n    if is_inpaint_model(model):\n        assert mask and len(mask) > 0, f'{model} requires a mask'","typeGuard":"def requires_mask(model: str) -> bool:\n    m = model.lower()\n    return 'lama' in m or 'migan' in m or 'mi-gan' in m","tryCatchPattern":"try:\n    post_edit(image=img, mask=None, model='lama')\nexcept HTTPException as e:\n    if e.status_code == 422 and 'requires an image mask' in e.detail:\n        mask = build_mask_from_selection(); post_edit(image=img, mask=mask, model='lama')","preventionTips":["Treat masks as mandatory for inpaint models in client code","Generate the mask in the same editor flow that initiates the edit","Advertise mask-required capability per model in your registry"],"tags":["inpainting","validation","http-422","mlx"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}