From 27f73672a1123d7b546412ce1400e2cc53ac1130 Mon Sep 17 00:00:00 2001 From: Harshil Kaneria Date: Tue, 3 Nov 2026 20:59:32 +0530 Subject: [PATCH] fix(logging): keep raw_request when a request has no metadata pre_call wrote raw_request into a new dict whenever litellm_params had no metadata or an empty one, so callbacks never saw it. SDK calls usually pass no metadata, which made log_raw_request_response do nothing for them Create the metadata dict on litellm_params when it is missing so the raw request reaches the callbacks --- litellm/litellm_core_utils/litellm_logging.py | 4 +++- .../test_litellm_logging.py | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index 97c019a2180..88e44f6bd5b 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -1677,7 +1677,9 @@ class Logging(LiteLLMLoggingBaseClass): # log raw request to provider (like LangFuse) -- if opted in. if self.log_raw_request_response is True or litellm.log_raw_request_response is True: _litellm_params: Final = self.model_call_details.get("litellm_params", {}) - _metadata: Final = _litellm_params.get("metadata", {}) or {} + if _litellm_params.get("metadata") is None: + _litellm_params["metadata"] = {} + _metadata: Final = _litellm_params["metadata"] try: self.model_call_details["raw_request_typed_dict"] = RawRequestTypedDict( raw_request_api_base=self._get_masked_api_base(str(additional_args.get("api_base") or "")), diff --git a/tests/unit/litellm_core_utils/test_litellm_logging.py b/tests/unit/litellm_core_utils/test_litellm_logging.py index 13e181b2b92..2ec1102bc18 100644 --- a/tests/unit/litellm_core_utils/test_litellm_logging.py +++ b/tests/unit/litellm_core_utils/test_litellm_logging.py @@ -8662,6 +8662,26 @@ def test_pre_call_redacts_and_masks_raw_request(logging_obj): assert "key=*****" in raw_api_base +@pytest.mark.parametrize("litellm_params", [{}, {"metadata": None}, {"metadata": {}}]) +def test_pre_call_keeps_raw_request_when_request_has_no_metadata(logging_obj, litellm_params): + """Callbacks read raw_request from litellm_params metadata, which SDK calls often leave unset.""" + logging_obj.model_call_details["litellm_params"] = litellm_params + logging_obj.log_raw_request_response = True + + logging_obj.pre_call( + input="hi", + api_key="", + additional_args={ + "api_base": "https://api.openai.com/v1/chat/completions", + "headers": {}, + "complete_input_dict": {"model": "gpt-4o-mini"}, + }, + ) + + raw_request = logging_obj.model_call_details["litellm_params"]["metadata"]["raw_request"] + assert "https://api.openai.com/v1/chat/completions" in raw_request + + _PRIVATE_RAW_REQUEST_ARGS: Final = { "api_base": "https://api.openai.com/v1/chat/completions", "headers": {},