From f703b19f56ecb2ca438c3b1d75f3b13db5f38e7d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 3 Sep 2026 01:11:08 +0000 Subject: [PATCH] fix(proxy): read LITELLM_ENABLE_MODEL_CONFIG_CREDENTIAL_OVERRIDES env var The credential routing docs offer the env var as an alternative to litellm_settings.enable_model_config_credential_overrides, but nothing ever read it, so enabling the feature that way left it inert. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/__init__.py | 4 ++- litellm/proxy/litellm_pre_call_utils.py | 1 - .../proxy/test_litellm_pre_call_utils.py | 32 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/litellm/__init__.py b/litellm/__init__.py index 41a3789ab0d..ad63ce3c75c 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -373,7 +373,9 @@ prompt_name_config_map: Dict[str, PromptSpec] = {} enable_preview_features: bool = False return_response_headers: bool = False # get response headers from LLM Api providers - example x-remaining-requests, enable_json_schema_validation: bool = False -enable_model_config_credential_overrides: bool = False +enable_model_config_credential_overrides: bool = ( + os.getenv("LITELLM_ENABLE_MODEL_CONFIG_CREDENTIAL_OVERRIDES", "false").lower() == "true" +) enable_key_alias_format_validation: bool = ( False # opt-in validation of key_alias format on /key/generate and /key/update ) diff --git a/litellm/proxy/litellm_pre_call_utils.py b/litellm/proxy/litellm_pre_call_utils.py index 20f83085286..5fb9e7c2da3 100644 --- a/litellm/proxy/litellm_pre_call_utils.py +++ b/litellm/proxy/litellm_pre_call_utils.py @@ -2380,7 +2380,6 @@ def _apply_credential_overrides_from_model_config( 5. Team default override (defaultconfig) 6. Deployment default (no action needed) """ - # Feature flag gate — disabled by default, opt in with litellm.enable_model_config_credential_overrides = True if not litellm.enable_model_config_credential_overrides: return diff --git a/tests/test_litellm/proxy/test_litellm_pre_call_utils.py b/tests/test_litellm/proxy/test_litellm_pre_call_utils.py index ee0e2014951..779d06899cb 100644 --- a/tests/test_litellm/proxy/test_litellm_pre_call_utils.py +++ b/tests/test_litellm/proxy/test_litellm_pre_call_utils.py @@ -2,6 +2,9 @@ import asyncio import copy import json import os +import subprocess +import sys +import textwrap import time from datetime import datetime, timezone from types import SimpleNamespace @@ -4951,6 +4954,35 @@ def test_apply_overrides_feature_flag_disabled_by_default(): assert "api_key" not in data +@pytest.mark.parametrize( + "env_value, expected", + [("true", True), ("True", True), ("false", False), (None, False)], +) +def test_credential_overrides_flag_reads_env_var_at_import(env_value, expected): + """LITELLM_ENABLE_MODEL_CONFIG_CREDENTIAL_OVERRIDES is read at import, so check it in a fresh interpreter.""" + env = {k: v for k, v in os.environ.items() if k != "LITELLM_ENABLE_MODEL_CONFIG_CREDENTIAL_OVERRIDES"} + if env_value is not None: + env["LITELLM_ENABLE_MODEL_CONFIG_CREDENTIAL_OVERRIDES"] = env_value + result = subprocess.run( + [ + sys.executable, + "-c", + textwrap.dedent( + """ + import litellm + print(litellm.enable_model_config_credential_overrides) + """ + ), + ], + capture_output=True, + text=True, + env=env, + timeout=180, + ) + assert result.returncode == 0, result.stderr + assert result.stdout.strip() == str(expected) + + def test_extract_credential_provider_hint_prefers_exact_match(): """Provider hint selects the correct provider in a multi-provider entry.""" entry = {