From f6915872fac8d5f94ce11f9872a73f4bfe0f2892 Mon Sep 17 00:00:00 2001 From: Harshit28j Date: Sat, 14 Mar 2026 16:32:18 +0530 Subject: [PATCH] fix: ensure metadata isolation for silent model metrics --- litellm/router.py | 5 +++++ tests/test_litellm/test_router_silent_experiment.py | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/litellm/router.py b/litellm/router.py index 8240d380410..56f6c5fa538 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -1357,6 +1357,11 @@ class Router: if "metadata" not in silent_kwargs: silent_kwargs["metadata"] = {} + # OTel spans are not safe to use across event loops. The silent + # experiment runs in a new event loop, so strip the span to prevent + # cross-loop tracing races or span corruption. + silent_kwargs["metadata"].pop("litellm_parent_otel_span", None) + silent_kwargs["metadata"]["is_silent_experiment"] = True # Pop logging objects and call IDs to ensure a fresh logging context diff --git a/tests/test_litellm/test_router_silent_experiment.py b/tests/test_litellm/test_router_silent_experiment.py index e2f916ca3d1..5c3a167621a 100644 --- a/tests/test_litellm/test_router_silent_experiment.py +++ b/tests/test_litellm/test_router_silent_experiment.py @@ -72,7 +72,11 @@ def test_get_silent_experiment_kwargs(): # so that setting model_group / is_silent_experiment on the silent dict # doesn't corrupt the primary call's metadata. assert result["metadata"] is not kwargs["metadata"] - # Original metadata must NOT be mutated + # OTel span must be stripped from the silent copy — it's not safe to use + # across event loops (silent experiment runs in a new event loop). + assert "litellm_parent_otel_span" not in result["metadata"] + # Original metadata must NOT be mutated — must carry the real span, + # not safe_deep_copy's temporary "placeholder" string. assert "is_silent_experiment" not in kwargs["metadata"] assert kwargs["metadata"]["litellm_parent_otel_span"] is mock_span assert kwargs["metadata"]["user_api_key_auth"] is mock_auth