From 714f9955a7b82c438a3485fc9d71fdd5a4ec5472 Mon Sep 17 00:00:00 2001 From: daleselaji-dev Date: Fri, 21 Aug 2026 10:44:52 +0800 Subject: [PATCH] fix(proxy): preserve Anthropic rate limit headers --- .../llm_response_utils/get_headers.py | 12 +++++++++++- .../test_exception_header_preservation.py | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/litellm/litellm_core_utils/llm_response_utils/get_headers.py b/litellm/litellm_core_utils/llm_response_utils/get_headers.py index f1ae6492e4e..c069d6ea656 100644 --- a/litellm/litellm_core_utils/llm_response_utils/get_headers.py +++ b/litellm/litellm_core_utils/llm_response_utils/get_headers.py @@ -1,5 +1,12 @@ from typing import Final +_PROVIDER_HEADERS_TO_PASSTHROUGH: Final = frozenset( + { + "anthropic-ratelimit-unified-status", + "retry-after", + } +) + def get_response_headers(_response_headers: dict | None = None) -> dict: """ @@ -28,7 +35,10 @@ def get_response_headers(_response_headers: dict | None = None) -> dict: if "x-ratelimit-remaining-tokens" in _response_headers: openai_headers["x-ratelimit-remaining-tokens"] = _response_headers["x-ratelimit-remaining-tokens"] llm_provider_headers: Final = _get_llm_provider_headers(_response_headers) - return {**llm_provider_headers, **openai_headers} + passthrough_headers: Final = { + key: value for key, value in _response_headers.items() if key.lower() in _PROVIDER_HEADERS_TO_PASSTHROUGH + } + return {**llm_provider_headers, **openai_headers, **passthrough_headers} def _get_llm_provider_headers(response_headers: dict) -> dict: diff --git a/tests/test_litellm/test_exception_header_preservation.py b/tests/test_litellm/test_exception_header_preservation.py index 6ea478c633b..e5345e6b6d3 100644 --- a/tests/test_litellm/test_exception_header_preservation.py +++ b/tests/test_litellm/test_exception_header_preservation.py @@ -278,6 +278,22 @@ class TestProxyHeaderExtraction: assert result.get("llm_provider-x-request-id") == "req-abc123" assert result.get("llm_provider-x-ms-region") == "eastus" + def test_get_response_headers_preserves_anthropic_rate_limit_headers(self): + """Anthropic-compatible clients need these headers on the downstream 429.""" + from litellm.litellm_core_utils.llm_response_utils.get_headers import ( + get_response_headers, + ) + + result = get_response_headers( + { + "Anthropic-RateLimit-Unified-Status": "rejected", + "Retry-After": "287441", + } + ) + + assert result["Anthropic-RateLimit-Unified-Status"] == "rejected" + assert result["Retry-After"] == "287441" + def test_proxy_can_extract_headers_from_exception_response(self): """Simulate how proxy extracts headers from exception.response.headers.""" from litellm.litellm_core_utils.llm_response_utils.get_headers import (