{"record":{"id":"e566d967e1d3c54b","repo":"BerriAI/litellm","slug":"raw-response-text-e566d9","errorCode":null,"errorMessage":"{raw_response.text}","messagePattern":"\\{raw_response\\.text\\}","errorType":"http","errorClass":"OpenAIError","httpStatus":null,"severity":"error","filePath":"litellm/llms/openai/image_edit/transformation.py","lineNumber":152,"sourceCode":"                mask_content_type: Final[str] = ImageEditRequestUtils.get_image_content_type(_mask)\n                if isinstance(_mask, BufferedReader):\n                    files_list.append((\"mask\", (_mask.name, _mask, mask_content_type)))\n                else:\n                    files_list.append((\"mask\", (\"mask.png\", _mask, mask_content_type)))\n\n        return data_without_files, files_list\n\n    def transform_image_edit_response(\n        self,\n        model: str,\n        raw_response: httpx.Response,\n        logging_obj: LiteLLMLoggingObj,\n    ) -> ImageResponse:\n        \"\"\"No transform applied since outputs are in OpenAI spec already\"\"\"\n        try:\n            raw_response_json: Final = raw_response.json()\n        except Exception:\n            raise OpenAIError(message=raw_response.text, status_code=raw_response.status_code)\n        return ImageResponse(**raw_response_json)\n\n    def validate_environment(\n        self,\n        headers: dict,\n        model: str,\n        api_key: str | None = None,\n        litellm_params: dict | None = None,\n        api_base: str | None = None,\n    ) -> dict:\n        api_key = api_key or litellm.api_key or litellm.openai_key or get_secret_str(\"OPENAI_API_KEY\")\n        headers.update(\n            {\n                \"Authorization\": f\"Bearer {api_key}\",\n            }\n        )\n        return headers\n","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/openai/image_edit/transformation.py#L134-L170","documentation":"After litellm sends an image edit request (images/edits endpoint), it tries raw_response.json(); if the body is not valid JSON it raises OpenAIError with the raw body text as the message and the upstream HTTP status code. The wrapper exists precisely because non-JSON error bodies (HTML gateways, empty replies) would otherwise produce an opaque JSONDecodeError.","triggerScenarios":"Calling litellm.image_edit() (gpt-image-1 / dall-e-2 edits) when the endpoint returns a non-JSON body: 502/504 HTML error pages from proxies or Cloudflare, empty responses from truncated uploads, malformed multipart payloads rejected by an intermediary, or OpenAI-compatible gateways that return plain-text errors.","commonSituations":"Self-hosted gateways or corporate proxies in front of api.openai.com returning HTML on overload; oversized image uploads getting cut off; custom OpenAI-compatible providers whose error responses are not JSON; brief outages where a CDN serves an error page instead of the API.","solutions":["Read OpenAIError.status_code and the message body: HTML like '502 Bad Gateway' implicates a proxy/CDN, so retry after the intermediary recovers","If a custom api_base is set, verify that endpoint returns JSON errors in OpenAI format (curl it directly and inspect Content-Type)","For large images, compress or reduce size to avoid truncated uploads producing non-JSON truncation errors","Retry transient 5xx gateway responses with exponential backoff; the request itself is usually valid"],"exampleFix":"# before\nresp = litellm.image_edit(model=\"gpt-image-1\", image=open(\"cat.png\",\"rb\"), prompt=\"add a hat\")\n# raises OpenAIError whose message is an HTML error page\n\n# after\nfrom litellm.exceptions import OpenAIError\n\ntry:\n    resp = litellm.image_edit(model=\"gpt-image-1\", image=open(\"cat.png\",\"rb\"), prompt=\"add a hat\")\nexcept OpenAIError as e:\n    if getattr(e, \"status_code\", 0) >= 500:\n        time.sleep(2)\n        resp = litellm.image_edit(model=\"gpt-image-1\", image=open(\"cat.png\",\"rb\"), prompt=\"add a hat\")\n    else:\n        raise","handlingStrategy":"try-catch","validationCode":"import os\n\n# avoid the truncated/gateway path: validate the input file before the call\npath = \"edit.png\"\nassert os.path.getsize(path) > 0, \"image file is empty\"\nwith open(path, \"rb\") as f:\n    head = f.read(8)\nassert head[:8] == b\"\\x89PNG\\r\\n\\x1a\\n\" or head[:3] == b\"\\xff\\xd8\\xff\", \"not a PNG/JPEG\"","typeGuard":null,"tryCatchPattern":"from litellm.exceptions import OpenAIError\n\ntry:\n    resp = litellm.image_edit(model=\"gpt-image-1\", image=img, prompt=p)\nexcept OpenAIError as e:\n    body = str(getattr(e, \"message\", e)) or \"\"\n    if getattr(e, \"status_code\", 0) >= 500 or \"<\" in body[:1]:  # gateway HTML page\n        time.sleep(2)\n        resp = litellm.image_edit(model=\"gpt-image-1\", image=img, prompt=p)\n    else:\n        raise","preventionTips":["Log OpenAIError.status_code and the first bytes of the message - HTML/plain-text bodies point at intermediaries, not the API","Validate image files (non-empty, correct magic bytes) before uploading","If using a custom api_base/gateway, confirm it returns JSON OpenAI-style errors with a quick curl probe","Retry 5xx/gateway responses with backoff; the edit request itself is usually valid"],"tags":["image-edit","json-parse","gateway","http-error","openai"],"backgroundTag":"non-json-response","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}