odysseus-dev/odysseus · error · HTTPException

Pillow is required for MLX image edit bridge inputs.

Error message

Pillow is required for MLX image edit bridge inputs.

What it means

Raised by _write_bridge_input_image in scripts/mlx_image_server.py when importing PIL (Pillow) fails while preparing the input PNG for the MLX Swift colorize/inpaint bridge. Pillow is an optional runtime dependency; without it the edits/harmonize endpoints cannot decode and re-encode the uploaded image, so the server returns HTTP 503.

Source

Thrown at scripts/mlx_image_server.py:178

def _weights_path(model: str) -> Path:
    p = Path(model).expanduser()
    if p.is_file():
        return p
    snap = _snapshot_path(model)
    if snap.is_file():
        return snap
    candidates = sorted(snap.rglob("*.safetensors"))
    if not candidates:
        raise HTTPException(500, f"No safetensors weights found for {model} in {snap}")
    return candidates[0]


def _write_bridge_input_image(raw: bytes, out_path: Path) -> None:
    try:
        from PIL import Image
        import io
    except Exception as e:
        raise HTTPException(503, "Pillow is required for MLX image edit bridge inputs.") from e
    try:
        img = Image.open(io.BytesIO(raw)).convert("RGBA")
        img.save(out_path, format="PNG")
    except Exception as e:
        raise HTTPException(400, f"Invalid input image: {e}") from e


def _write_bridge_mask(raw: bytes, out_path: Path) -> None:
    try:
        from PIL import Image
        import io
    except Exception as e:
        raise HTTPException(503, "Pillow is required for MLX image edit bridge masks.") from e
    try:
        img = Image.open(io.BytesIO(raw))
        if img.mode == "RGBA":
            # OpenAI edits mask convention: transparent = regenerate.
            alpha = img.getchannel("A")

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. pip install Pillow in the environment that launches mlx_image_server.py
  2. Verify with the same interpreter: python -c 'from PIL import Image'
  3. Recreate the venv if Pillow is installed but fails to import (broken C extension)

Example fix

# before
python scripts/mlx_image_server.py --model academictorrents/lama  # edits -> 503
# after
pip install Pillow
python scripts/mlx_image_server.py --model academictorrents/lama
Defensive patterns

Strategy: type-guard

Validate before calling

import importlib.util
if importlib.util.find_spec('PIL') is None:
    raise SystemExit('Pillow missing in server env; pip install Pillow')

Type guard

def has_pillow() -> bool:
    import importlib.util
    return importlib.util.find_spec('PIL') is not None

Prevention

When it happens

Trigger: POST /v1/images/edits or /v1/images/harmonize against a LaMa/MI-GAN/DDColor model when the launch Python lacks Pillow (import PIL raises).

Common situations: Minimal server venv where only fastapi/uvicorn were installed; PIL installed in a different environment than the one launching the server; Pillow broken by a mixed pip/conda install or an incompatible binary wheel after a Python upgrade.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/6369e5d9495f78af. Report an issue: GitHub.