{"record":{"id":"76ed0c4a5b1c691e","repo":"conductor-oss/conductor","slug":"image-generation-api-failed-with-status-d-s","errorCode":null,"errorMessage":"Image Generation API failed with status %d: %s","messagePattern":"Image Generation API failed with status (.+?): (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/providers/openai/api/OpenAIImageGenApi.java","lineNumber":76,"sourceCode":"        this(httpClient, apiKey, baseUrl, false);\n    }\n\n    public ImageResult createImage(ImageRequest request) throws IOException {\n        String jsonBody = objectMapper.writeValueAsString(request);\n\n        Request httpRequest =\n                new Request.Builder()\n                        .url(baseUrl + \"/images/generations\")\n                        .header(authHeaderName, authHeaderValue)\n                        .header(\"Content-Type\", \"application/json\")\n                        .post(RequestBody.create(jsonBody, JSON))\n                        .build();\n\n        try (Response response = httpClient.newCall(httpRequest).execute()) {\n            ResponseBody body = response.body();\n            String responseBody = body != null ? body.string() : \"\";\n            if (!response.isSuccessful()) {\n                throw new IOException(\n                        \"Image Generation API failed with status %d: %s\"\n                                .formatted(response.code(), responseBody));\n            }\n            return objectMapper.readValue(responseBody, ImageResult.class);\n        }\n    }\n\n    @JsonInclude(JsonInclude.Include.NON_NULL)\n    public record ImageRequest(\n            String model,\n            String prompt,\n            Integer n,\n            String size,\n            String style,\n            String quality,\n            @JsonProperty(\"response_format\") String responseFormat // \"url\" or \"b64_json\"\n            ) {\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/providers/openai/api/OpenAIImageGenApi.java#L58-L94","documentation":"OpenAIImageGenApi.createImage() throws IOException with message \"Image Generation API failed with status %d: %s\" when the HTTP response is not 2xx. The %d is the HTTP status code, %s is the raw response body. This is the low-level OkHttp client for POST {baseUrl}/images/generations.","triggerScenarios":"POST {baseUrl}/images/generations returns non-2xx. Common: 401 (invalid API key), 429 (rate limit — image generation rate limits are stricter than chat), 400 (invalid model, unsupported size/quality/N combination, content policy violation), 404 (wrong baseURL), 500 (server error).","commonSituations":"Using a non-image model name (gpt-4o instead of dall-e-3); requesting unsupported size for the model (dall-e-2 supports limited sizes vs dall-e-3); content-policy rejection of the prompt; rate limit from rapid image generation; API key without image generation access tier.","solutions":["Read the status code and body from the IOException message — OpenAI returns a JSON error with a 'error.message' field explaining the issue.","For 400 content-policy: revise the prompt to avoid policy violations.","For 400 invalid parameters: verify the model (dall-e-2, dall-e-3, gpt-image-1) and that the size/quality/N combination is supported.","For 429: implement backoff — image generation rate limits are significantly lower than chat.","For 401: verify the API key and that the account has image-generation access."],"exampleFix":"// before: requesting unsupported size on dall-e-2\nnew OpenAIImageGenApi.ImageRequest(\"dall-e-2\", \"a cat\", 1, \"1792x1024\", \"hd\", \"b64_json\")\n// after: use dall-e-3 for larger sizes, or a supported size for dall-e-2\nnew OpenAIImageGenApi.ImageRequest(\"dall-e-3\", \"a cat\", 1, \"1792x1024\", \"hd\", \"b64_json\")","handlingStrategy":"try-catch","validationCode":"// Validate image generation request before calling\nOpenAIImageGenApi.ImageRequest request = /* ... */;\nSet<String> imageModels = Set.of(\"dall-e-2\", \"dall-e-3\", \"gpt-image-1\");\nif (!imageModels.contains(request.model())) {\n    throw new IllegalArgumentException(\n        \"Model '\" + request.model() + \"' is not an image generation model. Use: \" + imageModels);\n}\nif (request.prompt() == null || request.prompt().isBlank()) {\n    throw new IllegalArgumentException(\"Prompt is required\");\n}","typeGuard":"null","tryCatchPattern":"int maxRetries = 2;\nfor (int attempt = 0; attempt <= maxRetries; attempt++) {\n    try {\n        return api.createImage(request);\n    } catch (IOException e) {\n        String msg = e.getMessage();\n        if (msg.contains(\"429\") && attempt < maxRetries) {\n            // Image gen has stricter rate limits — longer backoff\n            Thread.sleep(10000L * (attempt + 1));\n            continue;\n        }\n        // Content policy (400) or auth (401) — don't retry\n        throw e;\n    }\n}","preventionTips":["Validate the model is an image generation model (dall-e-2, dall-e-3, gpt-image-1).","Verify size/quality/N combinations are supported by the specific model.","Implement longer backoff for image generation rate limits.","Handle content-policy rejections with prompt revision, not retry.","Verify the API key has image-generation tier access."],"tags":["openai","image-generation","http-error","network","api-error","ai"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}