{"record":{"id":"349551f4769b3dc7","repo":"odysseus-dev/odysseus","slug":"image-edit-request-failed","errorCode":null,"errorMessage":"Image edit request failed","messagePattern":"Image edit request failed","errorType":"http","errorClass":"HTTPException","httpStatus":null,"severity":"error","filePath":"routes/gallery/gallery_routes.py","lineNumber":1489,"sourceCode":"                        logger.warning(\"inpaint_proxy self-hosted edits: status %s\", r.status_code)\n                        detail = \"Image edit request failed\"\n                        try:\n                            err = r.json()\n                            detail = err.get(\"detail\") or err.get(\"error\") or detail\n                        except Exception:\n                            pass\n                        # A plain SD/SDXL checkpoint often exposes\n                        # generation only at /images/edits.\n                        # That does not mean the endpoint cannot inpaint:\n                        # Odysseus diffusion_server.py has a dedicated\n                        # /images/inpaint route that can derive/fallback to\n                        # inpaint, img2img crop+composite, or txt2img\n                        # crop+composite. Fall through to that route instead\n                        # of surfacing \"does not support image edits\".\n                        if r.status_code == 400 and \"does not support image edits\" in str(detail).lower():\n                            logger.info(\"inpaint_proxy self-hosted edits unsupported; falling back to /images/inpaint\")\n                        else:\n                            raise HTTPException(r.status_code, detail)\n                except HTTPException:\n                    raise\n                except Exception:\n                    logger.exception(\"inpaint_proxy: failed to prepare self-hosted edit request\")\n                    raise HTTPException(400, \"Failed to prepare inpaint request\")\n\n                r = await client.post(_join_checked_gallery_endpoint(base, \"/images/inpaint\"), json=body)\n                if r.status_code != 200:\n                    logger.error(\"inpaint_proxy diffusion: status %s\", r.status_code)\n                    raise HTTPException(r.status_code, \"Inpaint request failed\")\n                return r.json()\n        except httpx.TimeoutException:\n            raise HTTPException(504, \"Inpaint request timed out (240s)\")\n        except HTTPException:\n            raise\n        except Exception:\n            logger.exception(\"inpaint_proxy: request failed\")\n            raise HTTPException(502, \"Inpaint request failed\")","sourceCodeStart":1471,"sourceCodeEnd":1507,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/gallery/gallery_routes.py#L1471-L1507","documentation":"Raised when the self-hosted /v1/images/edits call returns a status other than 200/404/405 (and not the specific 'does not support image edits' 400 that triggers fallback). The upstream status is forwarded and the detail is taken from the response's detail or error JSON field if parseable.","triggerScenarios":"POST to {base}/images/edits on the local diffusion path returning 401/403 (auth enabled), 422 (validation of the multipart payload), 500 (generation crash), or 503 (model still loading).","commonSituations":"Diffusion server restarted and the model checkpoint is loading (503); the wrapper added API auth the proxy does not send; schema drift in the multipart fields; CUDA OOM surfacing as 500.","solutions":["Read the forwarded status/detail and check the diffusion server logs for the matching request failure.","If 503/model-loading, wait for the model to finish loading and retry.","If 422, compare the multipart fields the proxy sends (model, prompt, size, n, image, mask) with what the server's /images/edits expects.","If 500 with CUDA OOM, lower resolution or free VRAM on the diffusion host."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    r = await client.post(\"/api/image/inpaint\", json=payload)\n    if r.status_code >= 400:\n        detail = r.json().get(\"detail\", \"\")\n        if r.status_code == 503:\n            await wait_model_loaded(base); r = await client.post(...)  # retry after load\n        else:\n            raise RuntimeError(f\"diffusion server rejected edit: {r.status_code} {detail}\")\nexcept httpx.HTTPError as e:\n    raise RuntimeError(f\"edit request transport failed: {e}\") from e","preventionTips":["Health-check the diffusion server (GET / or /internal/ping) before submitting edits.","Wait for model load on fresh server start before sending work.","Keep auth and payload schema aligned between proxy and server."],"tags":["self-hosted","diffusion-server","image-edit","upstream-error","proxy"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}