{"record":{"id":"17dcf76bf8f62b9b","repo":"BerriAI/litellm","slug":"error-text-17dcf7","errorCode":null,"errorMessage":"{error_text}","messagePattern":"\\{error_text\\}","errorType":"http","errorClass":"OpenAIError","httpStatus":null,"severity":"error","filePath":"litellm/llms/openai/image_variations/handler.py","lineNumber":110,"sourceCode":"                    status_code=200,\n                    request=httpx.Request(method=\"GET\", url=\"https://litellm.ai\"),  # mock request object\n                ),\n                logging_obj=logging_obj,\n                request_data=data,\n                image=image,\n                optional_params=optional_params,\n                litellm_params=litellm_params,\n                encoding=None,\n                api_key=api_key,\n            )\n        except Exception as e:\n            status_code: Final = getattr(e, \"status_code\", 500)\n            error_headers = getattr(e, \"headers\", None)\n            error_text: Final = getattr(e, \"text\", str(e))\n            error_response: Final = getattr(e, \"response\", None)\n            if error_headers is None and error_response:\n                error_headers = getattr(error_response, \"headers\", None)\n            raise OpenAIError(status_code=status_code, message=error_text, headers=error_headers)\n\n    def image_variations(\n        self,\n        model_response: ImageResponse,\n        api_key: str,\n        api_base: str,\n        model: str | None,\n        image: FileTypes,\n        timeout: float | None,\n        custom_llm_provider: str,\n        logging_obj: LiteLLMLoggingObj,\n        optional_params: dict,\n        litellm_params: dict,\n        print_verbose: Callable | None = None,\n        logger_fn=None,\n        client=None,\n        organization: str | None = None,\n        headers: dict | None = None,","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/openai/image_variations/handler.py#L92-L128","documentation":"litellm's image variations handler wraps any exception raised during the synchronous image-variation request (dall-e-2 /images/variations style calls) into an OpenAIError, extracting status_code (default 500), message text, and headers from the original exception. It is the single failure boundary for the whole non-streaming variation call - covering request build, HTTP send, and upstream API errors.","triggerScenarios":"Calling litellm.image_variations() when anything fails: invalid/expired API key (401), insufficient quota (429/402), invalid image payload, upstream 5xx, network timeouts, or a bad custom api_base. The original error's status and text are re-raised inside OpenAIError.","commonSituations":"Using dall-e-2 variation calls with rotated keys or exhausted credits; passing non-PNG/oversized source images; custom OpenAI-compatible endpoints that do not implement /images/variations; transient network failures surfacing with status 500 because the wrapped exception lacked a status_code.","solutions":["Check OpenAIError.status_code: 401 = fix api_key, 429 = quota/rate limit, 400 = invalid image/params, 5xx = retry later","Verify the input image meets requirements (PNG, size limits) for the variations endpoint","Confirm api_base targets an endpoint that actually implements /images/variations if using a proxy/custom base","Retry with backoff on 429/5xx; the call is idempotent for variations"],"exampleFix":"# before\nresp = litellm.image_variations(image=open(\"cat.png\",\"rb\"), model=\"dall-e-2\")\n# OpenAIError with masked cause\n\n# after\nfrom litellm.exceptions import OpenAIError\n\ntry:\n    resp = litellm.image_variations(image=open(\"cat.png\",\"rb\"), model=\"dall-e-2\")\nexcept OpenAIError as e:\n    if getattr(e, \"status_code\", 500) == 401:\n        raise RuntimeError(\"bad OPENAI_API_KEY\") from e\n    raise","handlingStrategy":"try-catch","validationCode":"import os\nfrom pathlib import Path\n\n# pre-flight checks for the variations call\ndef can_run_variation(image_path: str) -> bool:\n    p = Path(image_path)\n    if not p.exists() or p.stat().st_size == 0:\n        return False\n    with p.open(\"rb\") as f:\n        magic = f.read(8)\n    return magic.startswith(b\"\\x89PNG\\r\\n\\x1a\\n\")\n\nassert can_run_variation(\"cat.png\"), \"need a non-empty PNG\"\nassert os.getenv(\"OPENAI_API_KEY\"), \"need credentials\"","typeGuard":null,"tryCatchPattern":"from litellm.exceptions import OpenAIError\n\ntry:\n    resp = litellm.image_variations(image=open(\"cat.png\", \"rb\"), model=\"dall-e-2\")\nexcept OpenAIError as e:\n    code = getattr(e, \"status_code\", 500)\n    if code in (429, 500, 502, 503):\n        time.sleep(2)  # transient - retry\n        resp = litellm.image_variations(image=open(\"cat.png\", \"rb\"), model=\"dall-e-2\")\n    elif code == 401:\n        raise RuntimeError(\"invalid OPENAI_API_KEY\") from e\n    else:\n        raise","preventionTips":["Branch on OpenAIError.status_code rather than message text - the message is the forwarded upstream body","Validate the source image (PNG magic bytes, size, readability) before the call","Only dall-e-2 supports variations - check the model before invoking image_variations","Retry only 429/5xx; 4xx means your request/credentials are wrong and retries waste quota"],"tags":["image-variations","error-wrapping","openai","http-error"],"backgroundTag":"upstream-api-error","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}