conductor-oss/conductor · error · RuntimeException

Image generation API call failed:

Error message

Image generation API call failed: 

What it means

OpenAIHttpImageModel wraps an IOException from OpenAIImageGenApi.createImage() in a RuntimeException with message "Image generation API call failed: ". This is the HTTP-based image model used by the OpenAI provider (not Spring AI's built-in). The IOException originates from error 218 (non-2xx HTTP) or a network failure during POST /v1/images/generations.

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/providers/openai/OpenAIHttpImageModel.java:88

                            .n(options != null && options.getN() != null ? options.getN() : 1)
                            .size(size)
                            .style(style)
                            .responseFormat(responseFormat)
                            .build();

            var result = imageGenApi.createImage(request);

            List<ImageGeneration> generations = new ArrayList<>();
            if (result.data() != null) {
                for (var imageData : result.data()) {
                    Image image = new Image(imageData.url(), imageData.b64Json());
                    generations.add(new ImageGeneration(image));
                }
            }

            return new ImageResponse(generations);
        } catch (IOException e) {
            throw new RuntimeException("Image generation API call failed: " + e.getMessage(), e);
        }
    }
}

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Inspect getCause() for the IOException — the message contains the HTTP status and OpenAI error body (see error 218).
  2. Verify the model is an image model: dall-e-2, dall-e-3, or gpt-image-1.
  3. For content-policy rejections (400 with safety message), revise the prompt.
  4. For 429, implement backoff — image generation has lower rate limits than chat.

Example fix

// before
{"model": "gpt-4o", "prompt": "a cat"} // not an image model
// after
{"model": "dall-e-3", "prompt": "a cat"}
Defensive patterns

Strategy: try-catch

Validate before calling

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

Type guard

null

Try / catch

try {
    ImageResponse response = imageModel.call(prompt);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof IOException) {
        String msg = cause.getMessage();
        if (msg.contains("429")) {
            // Image gen rate limit — backoff longer than chat
            Thread.sleep(10000);
            return retry(prompt);
        }
    }
    throw e;
}

Prevention

When it happens

Trigger: An image-generation task calls OpenAIHttpImageModel.call() and the POST /v1/images/generations request fails: invalid image model (not dall-e-2/dall-e-3/gpt-image-1), 401 auth, 429 rate limit, content-policy rejection, or network error.

Common situations: Using a non-image model name; requesting features the model doesn't support (e.g. dall-e-2 doesn't support HD quality); content policy violation in the prompt; rate limit on image generation (which is stricter than chat); API key without image-generation access.

Related errors


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