odysseus-dev/odysseus · error · HTTPException
LaMa / MI-GAN inpainting requires an image mask. Use the edi
Error message
LaMa / MI-GAN inpainting requires an image mask. Use the editor inpaint/object-removal tool so Odysseus can send the mask.
What it means
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.
Source
Thrown at scripts/mlx_image_server.py:234
if not bridge:
raise _unsupported_swift_mlx_runtime(model)
with tempfile.TemporaryDirectory(prefix="odysseus-ddcolor-") as td:
inp = Path(td) / "input.png"
_write_bridge_input_image(image_raw, inp)
weights = _weights_path(model)
tier = "tiny" if "tiny" in model.lower() else "large"
_run_bridge([
bridge,
"--model", str(weights),
"--image", str(inp),
"--output", str(out_path),
"--tier", tier,
])
def _run_inpaint_bridge(model: str, image_raw: bytes, mask_raw: bytes | None, out_path: Path) -> None:
if not mask_raw:
raise HTTPException(
422,
"LaMa / MI-GAN inpainting requires an image mask. Use the editor inpaint/object-removal tool so Odysseus can send the mask.",
)
bridge = _resolve_bridge(["odysseus-mlx-inpaint", "mlx-lama-serve"])
if not bridge:
raise _unsupported_swift_mlx_runtime(model)
with tempfile.TemporaryDirectory(prefix="odysseus-mlx-inpaint-") as td:
inp = Path(td) / "input.png"
mask = Path(td) / "mask.png"
_write_bridge_input_image(image_raw, inp)
_write_bridge_mask(mask_raw, mask)
weights = _weights_path(model)
mode = "fast" if ("mi-gan" in model.lower() or "migan" in model.lower()) else "best"
_run_bridge([
bridge,
"--model", str(weights),
"--image", str(inp),
"--mask", str(mask),View on GitHub (pinned to f9235ebbf1)
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
Example fix
# before
files = {'image': open('photo.png','rb'), 'prompt': 'remove person'}
# after
files = {'image': open('photo.png','rb'), 'mask': open('person-mask.png','rb'), 'prompt': 'remove person'} Defensive patterns
Strategy: validation
Validate before calling
def validate_edit_request(image: bytes, mask: bytes | None, model: str) -> None:
assert image, 'image required'
if is_inpaint_model(model):
assert mask and len(mask) > 0, f'{model} requires a mask' Type guard
def requires_mask(model: str) -> bool:
m = model.lower()
return 'lama' in m or 'migan' in m or 'mi-gan' in m Try / catch
try:
post_edit(image=img, mask=None, model='lama')
except HTTPException as e:
if e.status_code == 422 and 'requires an image mask' in e.detail:
mask = build_mask_from_selection(); post_edit(image=img, mask=mask, model='lama') Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- endpoint_a/endpoint_b or endpoint_a_id/endpoint_b_id is requ
- Invalid mask image: {e}
- detail[-4000:]
- This MLX image pipeline requires a companion vision-language
- This MLX image endpoint supports text-to-image generation on
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/a2170212c0cabc0c.
Report an issue: GitHub.