diff --git a/litellm/utils.py b/litellm/utils.py index a7d7447d7f3..4a51336a862 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -4517,6 +4517,15 @@ def get_optional_params( unsupported_params[k] = non_default_params[k] if unsupported_params: + if "reasoning_effort" in unsupported_params and custom_llm_provider in ("openai", "azure"): + raise UnsupportedParamsError( + status_code=500, + message=( + f"{custom_llm_provider} does not support reasoning_effort for model={model}. " + "reasoning_effort cannot be silently dropped. To forward it to the provider, " + "send allowed_openai_params=['reasoning_effort'] in your request." + ), + ) if litellm.drop_params is True or (drop_params is not None and drop_params is True): for k in unsupported_params: non_default_params.pop(k, None) diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index a72aec07766..a0a7eff505e 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -6144,6 +6144,42 @@ class TestFinalOptionalParamsLineRedaction: assert "'temperature': 0.25" in printed +@pytest.mark.parametrize( + "custom_llm_provider, model", + [ + ("openai", "gpt-4.1"), + ("openai", "gpt-4.1-mini"), + ("openai", "gpt-4o"), + ("openai", "gpt-4o-mini"), + ("azure", "gpt-4.1"), + ("azure", "gpt-4.1-mini"), + ("azure", "gpt-4o"), + ("azure", "gpt-4o-mini"), + ("azure", "azure/eu/gpt-4o-2024-08-06"), + ], +) +@pytest.mark.parametrize("request_drop, global_drop", [(True, False), (None, True)]) +def test_unsupported_reasoning_effort_is_not_silently_dropped( + custom_llm_provider: str, + model: str, + request_drop: bool | None, + global_drop: bool, + monkeypatch: pytest.MonkeyPatch, +) -> None: + from litellm.utils import get_optional_params + + # https://github.com/BerriAI/litellm/issues/40470, verified 2026-10-02. + # https://github.com/BerriAI/litellm/pull/44060#discussion_r4159472144, verified 2026-10-02. + monkeypatch.setattr(litellm, "drop_params", global_drop) + with pytest.raises(litellm.UnsupportedParamsError, match="reasoning_effort"): + get_optional_params( + model=model, + custom_llm_provider=custom_llm_provider, + reasoning_effort="low", + drop_params=request_drop, + ) + + class TestDropParamsStringCoercion: @pytest.mark.parametrize("drop_params", ["true", "True", True]) def test_truthy_drop_params_drops_unsupported_temperature(self, drop_params, monkeypatch):