{"record":{"id":"5c47cbece80be82d","repo":"conductor-oss/conductor","slug":"chat-completions-api-call-failed","errorCode":null,"errorMessage":"Chat Completions API call failed: ","messagePattern":"Chat Completions API call failed: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/providers/openai/OpenAICompatChatModel.java","lineNumber":59,"sourceCode":" */\n@Slf4j\npublic class OpenAICompatChatModel implements ChatModel {\n\n    private final OpenAIChatCompletionsApi api;\n    private final ObjectMapper objectMapper = new ObjectMapper();\n\n    public OpenAICompatChatModel(OpenAIChatCompletionsApi api) {\n        this.api = api;\n    }\n\n    @Override\n    public ChatResponse call(Prompt prompt) {\n        try {\n            ChatCompletionRequest request = buildRequest(prompt);\n            ChatCompletionResult result = api.createChatCompletion(request);\n            return toSpringChatResponse(result);\n        } catch (IOException e) {\n            throw new RuntimeException(\"Chat Completions API call failed: \" + e.getMessage(), e);\n        }\n    }\n\n    private ChatCompletionRequest buildRequest(Prompt prompt) {\n        List<Message> messages = prompt.getInstructions();\n        ChatOptions options = prompt.getOptions();\n\n        List<MessageItem> items = new ArrayList<>();\n        for (Message msg : messages) {\n            items.addAll(convertMessage(msg));\n        }\n\n        String model = options != null ? options.getModel() : null;\n        Double temperature = options != null ? options.getTemperature() : null;\n        Double topP = options != null ? options.getTopP() : null;\n        Integer maxTokens = options != null ? options.getMaxTokens() : null;\n        List<String> stop = options != null ? options.getStopSequences() : null;\n        Double frequencyPenalty = options != null ? options.getFrequencyPenalty() : null;","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/providers/openai/OpenAICompatChatModel.java#L41-L77","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect getCause() for the IOException — its message includes the HTTP status code and response body (see error 216).","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).","Verify the API key is for the correct provider (not an OpenAI key used against Perplexity).","Verify the model name is offered by that specific compatible provider."],"exampleFix":"// before: Grok provider configured with OpenAI-compatible chat model\n// baseUrl=https://api.x.ai (missing /v1), model=gpt-4o (wrong provider)\n// after\n// baseUrl=https://api.x.ai/v1, model=grok-2","handlingStrategy":"retry","validationCode":"// Validate provider config before calling the chat model\nif (config.getApiKey() == null || config.getApiKey().isBlank()) {\n    throw new IllegalArgumentException(\"API key is required for OpenAI-compatible chat model\");\n}\nif (config.getBaseURL() == null || config.getBaseURL().isBlank()) {\n    throw new IllegalArgumentException(\"Base URL is required for OpenAI-compatible provider\");\n}\n// Verify the model name is not null\nif (input.getModel() == null || input.getModel().isBlank()) {\n    throw new IllegalArgumentException(\"Model name is required\");\n}","typeGuard":"null","tryCatchPattern":"try {\n    ChatResponse response = chatModel.call(prompt);\n} catch (RuntimeException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof IOException io) {\n        String msg = io.getMessage();\n        if (msg.contains(\"429\") || msg.contains(\"500\") || msg.contains(\"503\")) {\n            // Transient — retry with backoff\n            return retryWithBackoff(() -> chatModel.call(prompt));\n        }\n        log.error(\"Chat Completions API error: {}\", msg);\n    }\n    throw e;\n}","preventionTips":["Verify the API key matches the compatible provider (not an OpenAI key against Perplexity/xAI).","Verify the baseURL and completionsPath match the provider's API.","Verify the model name is offered by that provider.","Implement retry with exponential backoff for 429/5xx responses."],"tags":["openai-compatible","chat-completion","network","api-error","ai"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}