From ea0d92a3d870667de51f85512b87f28e758e0238 Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Fri, 1 May 2026 20:49:49 -0700 Subject: [PATCH] fix: remove traceback key instead of it being "" --- litellm/proxy/hooks/proxy_track_cost_callback.py | 9 ++++++++- .../proxy/spend_tracking/spend_log_error_logger.py | 9 ++++++--- .../proxy/hooks/test_proxy_track_cost_callback.py | 12 +++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/litellm/proxy/hooks/proxy_track_cost_callback.py b/litellm/proxy/hooks/proxy_track_cost_callback.py index 823e19025e4..ad32b18a543 100644 --- a/litellm/proxy/hooks/proxy_track_cost_callback.py +++ b/litellm/proxy/hooks/proxy_track_cost_callback.py @@ -83,7 +83,14 @@ class _ProxyDBLogger(CustomLogger): traceback_str=traceback_str, ) if should_suppress_spend_log_tracebacks(): - _error_information = {**_error_information, "traceback": ""} + # Drop the traceback key entirely so the per-row Metadata pane in + # the UI (which renders the JSON blob verbatim) doesn't show a + # noisy ``"traceback": ""`` line. Downstream consumers all use + # ``.get("traceback")`` / truthy checks, and the TypedDict marks + # the field as optional, so omitting is type-safe. + _error_information = { + k: v for k, v in _error_information.items() if k != "traceback" + } _metadata["error_information"] = _error_information _metadata = await _ProxyDBLogger._enrich_failure_metadata_with_key_info( diff --git a/litellm/proxy/spend_tracking/spend_log_error_logger.py b/litellm/proxy/spend_tracking/spend_log_error_logger.py index bcb90f9bbd4..cfe647b6600 100644 --- a/litellm/proxy/spend_tracking/spend_log_error_logger.py +++ b/litellm/proxy/spend_tracking/spend_log_error_logger.py @@ -12,9 +12,12 @@ The opt-in is a single env var, ``LITELLM_SUPPRESS_SPEND_LOG_TRACEBACKS=true``, gated by ``should_suppress_spend_log_tracebacks``. When it returns ``True``: * ``spend_log_error`` drops the traceback from the console / structured log record (this module), and - * the failure callback in ``proxy_track_cost_callback`` blanks the - ``error_information.traceback`` field on the SpendLogs row before it is - persisted, so the UI's per-row Metadata pane stays clean. + * the failure callback in ``proxy_track_cost_callback`` drops the + ``error_information.traceback`` field from the SpendLogs row before it is + persisted, so the UI's per-row Metadata pane (which renders the metadata + JSON verbatim) stays clean. The key is omitted entirely rather than set + to ``""`` — ``StandardLoggingPayloadErrorInformation`` marks the field + optional and every downstream consumer uses ``.get("traceback")``. At DEBUG the full traceback is always preserved so operators can still troubleshoot. The UI suppression follows the same gate. diff --git a/tests/test_litellm/proxy/hooks/test_proxy_track_cost_callback.py b/tests/test_litellm/proxy/hooks/test_proxy_track_cost_callback.py index ad8c01db0a5..771e10a54a0 100644 --- a/tests/test_litellm/proxy/hooks/test_proxy_track_cost_callback.py +++ b/tests/test_litellm/proxy/hooks/test_proxy_track_cost_callback.py @@ -1043,12 +1043,14 @@ async def test_failure_hook_keeps_error_information_traceback_by_default(monkeyp @pytest.mark.asyncio -async def test_failure_hook_blanks_error_information_traceback_when_env_set( +async def test_failure_hook_drops_error_information_traceback_when_env_set( monkeypatch, ): - """With the opt-in env var, the traceback in the SpendLogs row is blanked - so the per-row Metadata pane in the UI stays clean. The other fields - (error_class / error_message / error_code) are preserved.""" + """With the opt-in env var, the traceback key is omitted from the + SpendLogs row entirely so the per-row Metadata pane in the UI (which + renders ``error_information`` as a JSON blob) doesn't show a noisy empty + ``"traceback": ""`` line. The other fields (error_class / error_message / + error_code) are preserved.""" import logging from litellm._logging import verbose_proxy_logger @@ -1062,6 +1064,6 @@ async def test_failure_hook_blanks_error_information_traceback_when_env_set( verbose_proxy_logger.setLevel(original_level) error_information = metadata["error_information"] - assert error_information["traceback"] == "" + assert "traceback" not in error_information assert error_information["error_class"] == "RuntimeError" assert error_information["error_message"] == "boom-with-traceback"