diff --git a/litellm/proxy/spend_tracking/spend_tracking_utils.py b/litellm/proxy/spend_tracking/spend_tracking_utils.py index 8f85ecdd480..cd636494dc4 100644 --- a/litellm/proxy/spend_tracking/spend_tracking_utils.py +++ b/litellm/proxy/spend_tracking/spend_tracking_utils.py @@ -264,7 +264,7 @@ def get_spend_logs_id(call_type: str, response_obj: dict, kwargs: dict) -> str | kwargs.get("litellm_call_id"), ) resolved_id: Final = next( - (candidate for candidate in candidate_ids if isinstance(candidate, str) and candidate), None + (candidate for candidate in candidate_ids if isinstance(candidate, str) and candidate not in ("", "None")), None ) if resolved_id is not None and call_type == CallTypes.aretrieve_batch.value: return f"{resolved_id}{BATCH_COST_REQUEST_ID_SUFFIX}" diff --git a/tests/test_litellm/proxy/spend_tracking/test_spend_tracking_utils.py b/tests/test_litellm/proxy/spend_tracking/test_spend_tracking_utils.py index f471e3f8fbb..0f9cfdaffdb 100644 --- a/tests/test_litellm/proxy/spend_tracking/test_spend_tracking_utils.py +++ b/tests/test_litellm/proxy/spend_tracking/test_spend_tracking_utils.py @@ -4083,6 +4083,19 @@ def test_get_spend_logs_id_prefers_the_response_id_over_the_standard_logging_id( ) +def test_get_spend_logs_id_falls_back_when_the_standard_logging_id_is_none(): + ids = [ + get_spend_logs_id( + "acompletion", + {"id": None}, + {"litellm_call_id": call_id, "standard_logging_object": {"id": "None"}}, + ) + for call_id in ("call-id-1", "call-id-2") + ] + + assert ids == ["call-id-1", "call-id-2"] + + @pytest.mark.asyncio async def test_spend_log_request_id_is_the_message_id_a_bridged_streaming_caller_was_streamed(): """A streaming /v1/messages call against a non-Anthropic model is served a msg_ id the