fix(proxy): thread config_file_path through LiteLLM_JWTAuth.custom_validate

LiteLLM_JWTAuth.__init__ calls get_instance_fn(custom_validate) without
config_file_path, so an operator who configures custom_validate:
s3://bucket/module.fn in their YAML JWT auth section would hit the
runtime gate on startup and break their deployment.

Accept config_file_path as a non-field kwarg (popped before the
invalid-keys check), thread it into get_instance_fn, and pass it from
the startup-load callsite via the existing user_config_file_path
module-level path. Admin-API JWT config writes leave the kwarg at None
and still hit the gate.
This commit is contained in:
user
2026-05-13 18:29:42 +00:00
parent 14a3083d45
commit 9f9e21d463
2 changed files with 18 additions and 2 deletions
+9 -1
View File
@@ -4486,6 +4486,14 @@ class LiteLLM_JWTAuth(LiteLLMPydanticObjectBase):
#########################################################
def __init__(self, **kwargs: Any) -> None:
# ``config_file_path`` is a non-field kwarg threaded by the
# startup-load path so an operator-configured
# ``custom_validate: s3://bucket/module.fn`` resolves through
# the documented config-file flow. Pop before the invalid-keys
# check; the runtime gate in ``get_instance_fn`` refuses
# ``s3://`` / ``gcs://`` when this is None.
config_file_path = kwargs.pop("config_file_path", None)
# get the attribute names for this Pydantic model
allowed_keys = LiteLLM_JWTAuth.__annotations__.keys()
@@ -4499,7 +4507,7 @@ class LiteLLM_JWTAuth(LiteLLMPydanticObjectBase):
custom_validate = kwargs.get("custom_validate")
if custom_validate is not None:
fn = get_instance_fn(custom_validate)
fn = get_instance_fn(custom_validate, config_file_path=config_file_path)
validate_custom_validate_return_type(fn)
kwargs["custom_validate"] = fn
+9 -1
View File
@@ -6774,7 +6774,15 @@ class ProxyStartupEvent:
for k, v in general_settings["litellm_jwtauth"].items():
if isinstance(v, str) and v.startswith("os.environ/"):
general_settings["litellm_jwtauth"][k] = get_secret(v)
litellm_jwtauth = LiteLLM_JWTAuth(**general_settings["litellm_jwtauth"])
# ``user_config_file_path`` is set by ``ProxyConfig._get_config_from_file``
# during startup. Threading it through lets an operator-
# configured ``custom_validate: s3://...`` resolve through
# the runtime gate; admin-API JWT config writes (no config
# file context) hit the gate and refuse remote loads.
litellm_jwtauth = LiteLLM_JWTAuth(
config_file_path=user_config_file_path,
**general_settings["litellm_jwtauth"],
)
else:
litellm_jwtauth = LiteLLM_JWTAuth()
jwt_handler.update_environment(