{"record":{"id":"587bc0a7bc7b21d1","repo":"odysseus-dev/odysseus","slug":"rejected-endpoint-url-reason-587bc0","errorCode":null,"errorMessage":"Rejected endpoint URL: {reason}","messagePattern":"Rejected endpoint URL: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"routes/gallery/gallery_routes.py","lineNumber":1277,"sourceCode":"        \"\"\"Forward inpaint request. If the selected endpoint is OpenAI, re-shape\n        the request for /v1/images/edits (multipart, inverted mask). Otherwise\n        proxy through to a self-hosted diffusion server's /v1/images/inpaint.\"\"\"\n        import httpx\n        user = require_privilege(request, \"can_generate_images\")\n        body = await request.json()\n        # Use endpoint from request body (editor dropdown) or fall back to DB lookup.\n        # Store as requested_base to avoid carrying user input into the outbound request.\n        requested_base = (body.pop(\"_endpoint\", \"\") or \"\").rstrip(\"/\")\n        # SSRF hardening: validate a client-supplied endpoint before any\n        # outbound request (mirrors routes/embedding_routes.py).\n        if requested_base:\n            from src.url_safety import check_outbound_url\n            ok, reason = check_outbound_url(\n                requested_base,\n                block_private=os.getenv(\"IMAGE_BLOCK_PRIVATE_IPS\", \"false\").lower() == \"true\",\n            )\n            if not ok:\n                raise HTTPException(400, f\"Rejected endpoint URL: {reason}\")\n        chosen_model = (body.pop(\"_model\", \"\") or \"\").strip()\n        api_key = None\n        if not requested_base:\n            db = SessionLocal()\n            try:\n                ep = _first_visible_image_endpoint(db, user)\n                if not ep:\n                    raise HTTPException(400, \"No image generation endpoint configured. Serve a diffusion model via Cookbook first.\")\n                base = ep.base_url.rstrip(\"/\")\n                api_key = ep.api_key\n            finally:\n                db.close()\n        else:\n            # Resolve the client-supplied base to a registered visible endpoint.\n            # Admins are not exempted — gallery proxy routes must use a DB row\n            # so the outbound URL never depends directly on request-body input.\n            db = SessionLocal()\n            try:","sourceCodeStart":1259,"sourceCodeEnd":1295,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/gallery/gallery_routes.py#L1259-L1295","documentation":"Error \"Rejected endpoint URL: {reason}\" thrown in odysseus-dev/odysseus.","triggerScenarios":"Triggered when the corresponding server-side validation or runtime check at the recorded location rejects the request or operation and returns this error message to the caller.","commonSituations":"See trigger scenarios.","solutions":["Use an http(s) endpoint URL pointing at an allowed host.","Fix the endpoint URL; internal or malformed addresses are rejected."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}