{"record":{"id":"6a9c4d811625d7a4","repo":"odysseus-dev/odysseus","slug":"this-mlx-image-endpoint-supports-text-to-image-gen","errorCode":null,"errorMessage":"This MLX image endpoint supports text-to-image generation only. Use /v1/images/generations, or serve an edit/img2img-capable model.","messagePattern":"This MLX image endpoint supports text-to-image generation only\\. Use /v1/images/generations, or serve an edit/img2img-capable model\\.","errorType":"http","errorClass":"HTTPException","httpStatus":422,"severity":"error","filePath":"scripts/mlx_image_server.py","lineNumber":413,"sourceCode":"):\n    active_model = model or _args.model\n    if _is_lama_inpaint(active_model) or _is_ddcolor(active_model):\n        image_raw = await image.read()\n        mask_raw = await mask.read() if mask is not None else None\n        out_images = []\n        count = max(1, min(int(n or 1), 4))\n        for _ in range(count):\n            with tempfile.TemporaryDirectory(prefix=\"odysseus-mlx-edit-\") as td:\n                out_path = Path(td) / \"image.png\"\n                if _is_ddcolor(active_model):\n                    _run_ddcolor_bridge(active_model, image_raw, out_path)\n                else:\n                    _run_inpaint_bridge(active_model, image_raw, mask_raw, out_path)\n                if not out_path.exists():\n                    raise HTTPException(500, f\"MLX Swift bridge completed but did not write {out_path}\")\n                out_images.append({\"b64_json\": base64.b64encode(out_path.read_bytes()).decode(\"ascii\")})\n        return {\"created\": 0, \"data\": out_images}\n    raise HTTPException(\n        422,\n        \"This MLX image endpoint supports text-to-image generation only. \"\n        \"Use /v1/images/generations, or serve an edit/img2img-capable model.\",\n    )\n\n\n@app.post(\"/v1/images/harmonize\")\ndef harmonize_image(req: HarmonizeRequest):\n    active_model = _args.model\n    if _is_lama_inpaint(active_model) or _is_ddcolor(active_model):\n        try:\n            image_raw = base64.b64decode(req.image.split(\",\", 1)[-1])\n            mask_b64 = req.body_mask or req.mask\n            mask_raw = base64.b64decode(mask_b64.split(\",\", 1)[-1]) if mask_b64 else None\n        except Exception as e:\n            raise HTTPException(400, f\"Invalid base64 image payload: {e}\") from e\n        with tempfile.TemporaryDirectory(prefix=\"odysseus-mlx-harmonize-\") as td:\n            out_path = Path(td) / \"image.png\"","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/scripts/mlx_image_server.py#L395-L431","documentation":"Raised at the end of /v1/images/edits (and mirrored in /v1/images/harmonize) in scripts/mlx_image_server.py with HTTP 422 when the active model is not an edit-capable one (not DDColor, not LaMa/MI-GAN). The MLX server only supports edits for colorize/inpaint models; with a generation-only model (FLUX/HiDream/Boogu) the edits endpoint refuses up front.","triggerScenarios":"POST /v1/images/edits while the server runs with --model pointing at an mflux/HiDream/Boogu generation model, so both _is_ddcolor(active_model) and the inpaint branch fail and control falls through to this raise. Same for /v1/images/harmonize with such a model.","commonSituations":"Pointing an OpenAI-compatible client's images.edit call at a text-to-image MLX server; expecting img2img from flux-schnell which the server never routes to edits; model string not containing the lama/migan/ddcolor tokens the classifiers look for.","solutions":["Use POST /v1/images/generations for these models (prompt-only)","Relaunch the server with an edit-capable model (LaMa/MI-GAN inpaint or DDColor colorize) to serve /v1/images/edits","If you need diffusion img2img, use the diffusers-based diffusion_server.py instead, which supports pipelines accepting an image argument"],"exampleFix":"# before: server launched with --model black-forest-labs/FLUX.1-schnell\nclient.images.edit(image=f, prompt='...')  # 422\n# after\nclient.images.generate(prompt='...')  # or relaunch server with a lama/migan/ddcolor model","handlingStrategy":"type-guard","validationCode":"def is_edit_capable(model: str) -> bool:\n    m = model.lower()\n    return 'lama' in m or 'migan' in m or 'mi-gan' in m or 'ddcolor' in m\n\nif not is_edit_capable(active_model):\n    use_generations_endpoint()  # skip the edits call entirely","typeGuard":"def supports_mlx_edits(model: str) -> bool:\n    m = model.lower()\n    return any(k in m for k in ('lama', 'migan', 'mi-gan', 'ddcolor'))","tryCatchPattern":"try:\n    r = client.images.edit(image=f, prompt=p)\nexcept HTTPException as e:\n    if e.status_code == 422 and 'text-to-image generation only' in str(e.detail):\n        r = client.images.generate(prompt=p)\n    else:\n        raise","preventionTips":["Route edits only to LaMa/MI-GAN/DDColor-served instances","Keep a model->endpoints capability map in the client","Prefer the diffusions server when img2img is required"],"tags":["mlx","http-422","image-editing","routing"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}