fix(logging): use an empty list for read-call messages

A tuple matches no branch in the loggers that walk this value, so lunary's
parse_messages falls through to clean_message and raises AttributeError on the
success hook. An empty list reads as no messages everywhere: it satisfies the
isinstance(list) checks in newrelic, mlflow and datadog, iterates zero times in
traceloop and helicone, and is what StandardLoggingPayload.messages is typed to
hold. None would be type-legal too but is not iterable, so it trades one crash
for another in mlflow and traceloop.
This commit is contained in:
Yucheng Zhu 2026-08-26 00:18:49 -07:00
parent 1c9e8013b7
commit 6fd74527ba
2 changed files with 13 additions and 3 deletions

View file

@ -1073,7 +1073,7 @@ def function_setup(
verbose_logger.debug("Error extracting messages from Google contents: %s", e)
messages = "default-message-value"
elif call_type in NON_INFERENCE_CALL_TYPES:
messages = ()
messages = [] # mutable-ok: loggers require a list here and Logging copies it
else:
messages = "default-message-value"
stream = False

View file

@ -4953,15 +4953,25 @@ class TestNonInferenceCallTypesAreNotBilled:
assert payload is not None
assert payload["total_tokens"] == 6000
def test_read_calls_do_not_log_a_placeholder_chat_message(self):
def _read_call_messages(self):
logging_obj, _ = litellm.utils.function_setup(
original_function="aget_responses",
rules_obj=litellm.utils.Rules(),
start_time=time.time(),
**{"litellm_call_id": "lit5602-setup", "response_id": "resp_lit5602"},
)
return logging_obj.model_call_details["messages"]
assert logging_obj.model_call_details["messages"] == ()
def test_read_calls_do_not_log_a_placeholder_chat_message(self):
assert self._read_call_messages() == []
def test_read_call_messages_survive_a_logger_that_walks_them(self):
"""Loggers reach into this value expecting a chat history and branch on it being a list.
An empty list reads as no messages; a tuple matches no branch and crashes the success hook,
and None is not iterable where other loggers walk it."""
from litellm.integrations.lunary import parse_messages
assert parse_messages(self._read_call_messages()) == []
def _build_success_payload(logging_obj, kwargs):