conductor-oss/conductor · error · IOException

Image Generation API failed with status %d: %s

Error message

Image Generation API failed with status %d: %s

What it means

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.

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/providers/openai/api/OpenAIImageGenApi.java:76

        this(httpClient, apiKey, baseUrl, false);
    }

    public ImageResult createImage(ImageRequest request) throws IOException {
        String jsonBody = objectMapper.writeValueAsString(request);

        Request httpRequest =
                new Request.Builder()
                        .url(baseUrl + "/images/generations")
                        .header(authHeaderName, authHeaderValue)
                        .header("Content-Type", "application/json")
                        .post(RequestBody.create(jsonBody, JSON))
                        .build();

        try (Response response = httpClient.newCall(httpRequest).execute()) {
            ResponseBody body = response.body();
            String responseBody = body != null ? body.string() : "";
            if (!response.isSuccessful()) {
                throw new IOException(
                        "Image Generation API failed with status %d: %s"
                                .formatted(response.code(), responseBody));
            }
            return objectMapper.readValue(responseBody, ImageResult.class);
        }
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public record ImageRequest(
            String model,
            String prompt,
            Integer n,
            String size,
            String style,
            String quality,
            @JsonProperty("response_format") String responseFormat // "url" or "b64_json"
            ) {

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Read the status code and body from the IOException message — OpenAI returns a JSON error with a 'error.message' field explaining the issue.
  2. For 400 content-policy: revise the prompt to avoid policy violations.
  3. 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.
  4. For 429: implement backoff — image generation rate limits are significantly lower than chat.
  5. For 401: verify the API key and that the account has image-generation access.

Example fix

// before: requesting unsupported size on dall-e-2
new OpenAIImageGenApi.ImageRequest("dall-e-2", "a cat", 1, "1792x1024", "hd", "b64_json")
// after: use dall-e-3 for larger sizes, or a supported size for dall-e-2
new OpenAIImageGenApi.ImageRequest("dall-e-3", "a cat", 1, "1792x1024", "hd", "b64_json")
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate image generation request before calling
OpenAIImageGenApi.ImageRequest request = /* ... */;
Set<String> imageModels = Set.of("dall-e-2", "dall-e-3", "gpt-image-1");
if (!imageModels.contains(request.model())) {
    throw new IllegalArgumentException(
        "Model '" + request.model() + "' is not an image generation model. Use: " + imageModels);
}
if (request.prompt() == null || request.prompt().isBlank()) {
    throw new IllegalArgumentException("Prompt is required");
}

Type guard

null

Try / catch

int maxRetries = 2;
for (int attempt = 0; attempt <= maxRetries; attempt++) {
    try {
        return api.createImage(request);
    } catch (IOException e) {
        String msg = e.getMessage();
        if (msg.contains("429") && attempt < maxRetries) {
            // Image gen has stricter rate limits — longer backoff
            Thread.sleep(10000L * (attempt + 1));
            continue;
        }
        // Content policy (400) or auth (401) — don't retry
        throw e;
    }
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of conductor-oss/conductor@cf7c3e4a8a (2026-08-14). Data as JSON: /api/errors/76ed0c4a5b1c691e. Report an issue: GitHub.