From cfe0b774aeaaebe3f9b0cb0760fd3256e47e23d6 Mon Sep 17 00:00:00 2001 From: xianren Date: Mon, 27 Apr 2026 22:01:27 +0800 Subject: [PATCH] fix(health-check): strip max_tokens before non-chat handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `_update_litellm_params_for_health_check` unconditionally injects `messages` and `max_tokens` (resolved via `_resolve_health_check_max_tokens` / `BACKGROUND_HEALTH_CHECK_MAX_TOKENS`) into the litellm params for every deployment. `_filter_model_params` was only stripping `messages`, so `max_tokens` reached every non-chat handler in `HealthCheckHelpers.get_mode_handlers` — image/video generation, embedding, rerank, audio_speech, audio_transcription, ocr, responses, batch. OpenAI's image-generation endpoints (dall-e-2, dall-e-3, gpt-image-1) are strict and return 400 `Unknown parameter: 'max_tokens'`, so any deployment with `mode: image_generation` is permanently reported unhealthy in the proxy UI. Manually calling `litellm.aimage_generation(...)` works fine; only the automated health check fails. Other providers happen to silently drop unknown fields, hiding the issue. Strip both `messages` and `max_tokens` in `_filter_model_params`. `acompletion` is the only mode handler that consumes `model_params` unfiltered, so this leaves chat health checks unaffected. The other handlers don't accept `max_tokens` to begin with. --- .../litellm_core_utils/health_check_utils.py | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/litellm/litellm_core_utils/health_check_utils.py b/litellm/litellm_core_utils/health_check_utils.py index ff252855f0d..874d260eba7 100644 --- a/litellm/litellm_core_utils/health_check_utils.py +++ b/litellm/litellm_core_utils/health_check_utils.py @@ -2,10 +2,29 @@ Utils used for litellm.ahealth_check() """ +#: litellm params that ``_update_litellm_params_for_health_check`` injects for +#: chat-completion health checks but that are invalid (or rejected) on every +#: other handler in :class:`HealthCheckHelpers.get_mode_handlers` — image and +#: video generation, embeddings, audio speech / transcription, rerank, ocr, +#: responses, batch, etc. ``messages`` is always chat-only; ``max_tokens`` is +#: chat/completion-only and is rejected by strict providers (e.g. OpenAI's +#: image-generation endpoints return 400 ``Unknown parameter: 'max_tokens'``). +_NON_CHAT_HEALTH_CHECK_STRIP_KEYS = {"messages", "max_tokens"} + def _filter_model_params(model_params: dict) -> dict: - """Remove 'messages' param from model params.""" - return {k: v for k, v in model_params.items() if k != "messages"} + """Strip chat-only params before invoking a non-chat health check handler. + + ``litellm.acompletion`` is the only mode handler that consumes + ``model_params`` unfiltered; every other handler routes through this + helper, so removing chat-completion-only keys here keeps strict providers + (OpenAI image generation, etc.) from rejecting the request. + """ + return { + k: v + for k, v in model_params.items() + if k not in _NON_CHAT_HEALTH_CHECK_STRIP_KEYS + } def _create_health_check_response(response_headers: dict) -> dict: