{"record":{"id":"8a844411fdead733","repo":"odysseus-dev/odysseus","slug":"pillow-is-required-for-mlx-image-edit-bridge-masks","errorCode":null,"errorMessage":"Pillow is required for MLX image edit bridge masks.","messagePattern":"Pillow is required for MLX image edit bridge masks\\.","errorType":"http","errorClass":"HTTPException","httpStatus":503,"severity":"error","filePath":"scripts/mlx_image_server.py","lineNumber":191,"sourceCode":"def _write_bridge_input_image(raw: bytes, out_path: Path) -> None:\n    try:\n        from PIL import Image\n        import io\n    except Exception as e:\n        raise HTTPException(503, \"Pillow is required for MLX image edit bridge inputs.\") from e\n    try:\n        img = Image.open(io.BytesIO(raw)).convert(\"RGBA\")\n        img.save(out_path, format=\"PNG\")\n    except Exception as e:\n        raise HTTPException(400, f\"Invalid input image: {e}\") from e\n\n\ndef _write_bridge_mask(raw: bytes, out_path: Path) -> None:\n    try:\n        from PIL import Image\n        import io\n    except Exception as e:\n        raise HTTPException(503, \"Pillow is required for MLX image edit bridge masks.\") from e\n    try:\n        img = Image.open(io.BytesIO(raw))\n        if img.mode == \"RGBA\":\n            # OpenAI edits mask convention: transparent = regenerate.\n            alpha = img.getchannel(\"A\")\n            mask = alpha.point(lambda p: 255 if p < 128 else 0)\n        else:\n            mask = img.convert(\"L\")\n        mask.save(out_path, format=\"PNG\")\n    except Exception as e:\n        raise HTTPException(400, f\"Invalid mask image: {e}\") from e\n\n\ndef _run_bridge(cmd: list[str]) -> None:\n    env = os.environ.copy()\n    proc = subprocess.run(cmd, env=env, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n    if proc.returncode != 0:\n        detail = (proc.stderr or proc.stdout or \"MLX Swift bridge failed\").strip()","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/scripts/mlx_image_server.py#L173-L209","documentation":"Raised by _write_bridge_mask in scripts/mlx_image_server.py when importing PIL fails while normalizing the uploaded mask PNG for the inpainting bridge (sibling of the input-image Pillow check). Without Pillow the server cannot apply the OpenAI alpha-transparency mask convention, so it returns HTTP 503.","triggerScenarios":"POST /v1/images/edits with a mask file against a LaMa/MI-GAN model when the launch Python cannot import PIL.","commonSituations":"Same as 943: server venv missing Pillow, wrong interpreter used at launch, or a broken Pillow install; often both 943 and 945 trigger together since the input image is written before the mask.","solutions":["pip install Pillow in the server's launch environment","Verify import with the exact interpreter (python -c 'from PIL import Image')","Reinstall Pillow if the import fails with an OSError about the C extension"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"import importlib.util\nassert importlib.util.find_spec('PIL'), 'install Pillow before serving edits'","typeGuard":"def has_pillow() -> bool:\n    import importlib.util\n    return importlib.util.find_spec('PIL') is not None","tryCatchPattern":null,"preventionTips":["Same preflight as 943: assert Pillow importable at server startup","Keep one requirements file for the server including Pillow"],"tags":["pillow","mlx","dependency","http-503"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}