From 17c858b02d3d9ea80dbf5ba9dcbcecbf1f06de2d Mon Sep 17 00:00:00 2001 From: willcai1984 Date: Thu, 30 Jul 2026 10:36:52 +0800 Subject: [PATCH] fix(health): fix chatgpt provider Test Connection endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs caused the LiteLLM UI "Test Connection" button to always fail for chatgpt provider models (e.g. chatgpt/gpt-5.6-sol, gpt-5.6-terra): 1. litellm/main.py — ahealth_check() mode auto-detection uses the model_cost map, but unlisted chatgpt models (any model not explicitly registered) fell through to the "chat" fallback. The chatgpt provider routes exclusively through the Responses API; sending a Chat Completions messages payload caused the backend to reject with: ChatgptException - {"detail": "Input must be a list"}. Fix: after get_llm_provider() resolves custom_llm_provider=="chatgpt" and mode is still None, default to "responses" instead of "chat". 2. litellm/litellm_core_utils/health_check_helpers.py — the "responses" mode handler passed input=prompt (a plain string) to litellm.aresponses(). The Responses API requires input to be a list of message objects, not a bare string. The ChatGPT/Codex backend rejected this with: ChatgptException - {"error": {"message": "Invalid type for 'input[0]': expected an input item, but got a string instead."}} Fix: pass input=[{"role": "user", "content": prompt or "test"}]. Both fixes were validated end-to-end against a live chatgpt provider deployment (gpt-5.6-sol, gpt-5.6-terra, two seats each — all returned status: success after the patch). --- litellm/litellm_core_utils/health_check_helpers.py | 2 +- litellm/main.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/health_check_helpers.py b/litellm/litellm_core_utils/health_check_helpers.py index a0f027cd58f..d1381e06bcf 100644 --- a/litellm/litellm_core_utils/health_check_helpers.py +++ b/litellm/litellm_core_utils/health_check_helpers.py @@ -251,7 +251,7 @@ class HealthCheckHelpers: ), "responses": lambda: litellm.aresponses( **_filter_model_params(model_params=model_params), - input=prompt or "test", + input=[{"role": "user", "content": prompt or "test"}], ), "ocr": lambda: litellm.aocr( **_filter_model_params(model_params=model_params), diff --git a/litellm/main.py b/litellm/main.py index 6c85adf3ae8..3923dc91701 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -8755,6 +8755,10 @@ async def ahealth_check( mode = litellm.model_cost[model].get("mode") model_params["cache"] = {"no-cache": True} # don't used cached responses for making health check calls + # chatgpt provider uses the Responses API exclusively; default to "responses" so the + # health check doesn't send a Chat Completions payload that the backend rejects. + if mode is None and custom_llm_provider == "chatgpt": + mode = "responses" mode = mode or "chat" if "*" in model: return await HealthCheckHelpers.ahealth_check_wildcard_models(