conductor-oss/conductor · error · RuntimeException

Chat Completions API call failed:

Error message

Chat Completions API call failed: 

What it means

OpenAICompatChatModel.call() wraps an IOException from OpenAIChatCompletionsApi.createChatCompletion() in a RuntimeException with message "Chat Completions API call failed: ". This model is used by OpenAI-compatible providers (Perplexity, Grok/xAI, Together AI, etc.) that use the Chat Completions format rather than the Responses API. The IOException originates from error 216 (non-2xx HTTP) or a network failure.

Source

Thrown at ai/src/main/java/org/conductoross/conductor/ai/providers/openai/OpenAICompatChatModel.java:59

 */
@Slf4j
public class OpenAICompatChatModel implements ChatModel {

    private final OpenAIChatCompletionsApi api;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public OpenAICompatChatModel(OpenAIChatCompletionsApi api) {
        this.api = api;
    }

    @Override
    public ChatResponse call(Prompt prompt) {
        try {
            ChatCompletionRequest request = buildRequest(prompt);
            ChatCompletionResult result = api.createChatCompletion(request);
            return toSpringChatResponse(result);
        } catch (IOException e) {
            throw new RuntimeException("Chat Completions API call failed: " + e.getMessage(), e);
        }
    }

    private ChatCompletionRequest buildRequest(Prompt prompt) {
        List<Message> messages = prompt.getInstructions();
        ChatOptions options = prompt.getOptions();

        List<MessageItem> items = new ArrayList<>();
        for (Message msg : messages) {
            items.addAll(convertMessage(msg));
        }

        String model = options != null ? options.getModel() : null;
        Double temperature = options != null ? options.getTemperature() : null;
        Double topP = options != null ? options.getTopP() : null;
        Integer maxTokens = options != null ? options.getMaxTokens() : null;
        List<String> stop = options != null ? options.getStopSequences() : null;
        Double frequencyPenalty = options != null ? options.getFrequencyPenalty() : null;

View on GitHub (pinned to cf7c3e4a8a)

Solutions

  1. Inspect getCause() for the IOException — its message includes the HTTP status code and response body (see error 216).
  2. Verify the baseURL and completionsPath match the provider's API (e.g. Perplexity uses https://api.perplexity.ai, xAI uses https://api.x.ai/v1).
  3. Verify the API key is for the correct provider (not an OpenAI key used against Perplexity).
  4. Verify the model name is offered by that specific compatible provider.

Example fix

// before: Grok provider configured with OpenAI-compatible chat model
// baseUrl=https://api.x.ai (missing /v1), model=gpt-4o (wrong provider)
// after
// baseUrl=https://api.x.ai/v1, model=grok-2
Defensive patterns

Strategy: retry

Validate before calling

// Validate provider config before calling the chat model
if (config.getApiKey() == null || config.getApiKey().isBlank()) {
    throw new IllegalArgumentException("API key is required for OpenAI-compatible chat model");
}
if (config.getBaseURL() == null || config.getBaseURL().isBlank()) {
    throw new IllegalArgumentException("Base URL is required for OpenAI-compatible provider");
}
// Verify the model name is not null
if (input.getModel() == null || input.getModel().isBlank()) {
    throw new IllegalArgumentException("Model name is required");
}

Type guard

null

Try / catch

try {
    ChatResponse response = chatModel.call(prompt);
} catch (RuntimeException e) {
    Throwable cause = e.getCause();
    if (cause instanceof IOException io) {
        String msg = io.getMessage();
        if (msg.contains("429") || msg.contains("500") || msg.contains("503")) {
            // Transient — retry with backoff
            return retryWithBackoff(() -> chatModel.call(prompt));
        }
        log.error("Chat Completions API error: {}", msg);
    }
    throw e;
}

Prevention

When it happens

Trigger: The chat model's call(Prompt) is invoked (via Spring AI ChatModel interface, typically through LLMHelper chat-completion flow) and the POST /chat/completions request fails: auth error, rate limit, invalid model, or network timeout at the compatible endpoint.

Common situations: Wrong API key for the compatible provider (Perplexity, xAI, Together); baseURL pointing to the wrong endpoint (missing /v1 or wrong path); model name not supported by the compatible provider; network connectivity to the third-party API.

Related errors


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