fix(langfuse): guard against None standard_callback_dynamic_params

Fix AttributeError: 'NoneType' object has no attribute 'get' when Langfuse
is configured via environment variables (no per-request dynamic params).

In _dynamic_langfuse_credentials_are_passed() and
get_dynamic_langfuse_logging_config(), standard_callback_dynamic_params can
be None (not {}). Calling .get() directly on None raises AttributeError.

Fix: use params = standard_callback_dynamic_params or {} before calling .get().

Added regression tests for both functions to ensure None is handled correctly.

Fixes: BerriAI/litellm#25940
This commit is contained in:
Aman Sachan 2026-05-13 02:06:55 +00:00
parent be2552bead
commit ccb3afb3e2
No known key found for this signature in database
GPG key ID: D50A9E263569B417
2 changed files with 45 additions and 8 deletions

View file

@ -140,13 +140,15 @@ class LangFuseHandler:
If no dynamic parameters are provided, it uses the `globalLangfuseLogger` values
"""
# only use dynamic params if langfuse credentials are passed dynamically
# Guard against None to handle the case where no per-request params are passed
params = standard_callback_dynamic_params or {}
return LangfuseLoggingConfig(
langfuse_secret=standard_callback_dynamic_params.get("langfuse_secret")
or standard_callback_dynamic_params.get("langfuse_secret_key"),
langfuse_public_key=standard_callback_dynamic_params.get(
langfuse_secret=params.get("langfuse_secret")
or params.get("langfuse_secret_key"),
langfuse_public_key=params.get(
"langfuse_public_key"
),
langfuse_host=standard_callback_dynamic_params.get("langfuse_host"),
langfuse_host=params.get("langfuse_host"),
)
@staticmethod
@ -159,12 +161,14 @@ class LangFuseHandler:
Returns:
bool: True if the dynamic langfuse credentials are passed, False otherwise
"""
# Guard against None to handle the case where no per-request params are passed (credentials come from env vars)
params = standard_callback_dynamic_params or {}
if (
standard_callback_dynamic_params.get("langfuse_host") is not None
or standard_callback_dynamic_params.get("langfuse_public_key") is not None
or standard_callback_dynamic_params.get("langfuse_secret") is not None
or standard_callback_dynamic_params.get("langfuse_secret_key") is not None
params.get("langfuse_host") is not None
or params.get("langfuse_public_key") is not None
or params.get("langfuse_secret") is not None
or params.get("langfuse_secret_key") is not None
):
return True
return False

View file

@ -127,3 +127,36 @@ def test_langfuse_handler_accepts_secret_key_alias(monkeypatch):
assert captured["allow_env_credentials"] is False
assert captured["cached_service_name"] == "langfuse"
assert captured["cached_logging_obj"] is logger
def test_dynamic_langfuse_credentials_are_passed_handles_none(monkeypatch):
"""Regression test: _dynamic_langfuse_credentials_are_passed must not crash when standard_callback_dynamic_params is None.
When Langfuse is configured via environment variables (no per-request dynamic params),
standard_callback_dynamic_params is None, not {}. The function must not raise
AttributeError: 'NoneType' object has no attribute 'get'.
"""
monkeypatch.setenv("LANGFUSE_PUBLIC_KEY", "pk-test")
monkeypatch.setenv("LANGFUSE_SECRET_KEY", "sk-test")
monkeypatch.setenv("LANGFUSE_HOST", "https://langfuse.example")
# Should return False (no dynamic params passed), not raise AttributeError
result = LangFuseHandler._dynamic_langfuse_credentials_are_passed(None)
assert result is False
def test_get_dynamic_langfuse_logging_config_handles_none(monkeypatch):
"""Regression test: get_dynamic_langfuse_logging_config must not crash when standard_callback_dynamic_params is None.
When Langfuse is configured via environment variables, standard_callback_dynamic_params is None.
The function should return a config with None values (relying on env var fallback downstream).
"""
monkeypatch.setenv("LANGFUSE_PUBLIC_KEY", "pk-test")
monkeypatch.setenv("LANGFUSE_SECRET_KEY", "sk-test")
monkeypatch.setenv("LANGFUSE_HOST", "https://langfuse.example")
# Should not raise AttributeError
config = LangFuseHandler.get_dynamic_langfuse_logging_config(None)
assert config.langfuse_public_key is None
assert config.langfuse_secret is None
assert config.langfuse_host is None