From c1323e20d90e95acb7ab0693fc3df37da6324c5f Mon Sep 17 00:00:00 2001 From: weiguangli-io Date: Mon, 27 Apr 2026 19:45:33 +0800 Subject: [PATCH] fix(aiohttp): sanitize non-ASCII response headers before passing to httpx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #26548. aiohttp decodes response header values as UTF-8 strings, but httpx.Headers internally calls .encode("ascii") which raises UnicodeEncodeError when headers contain non-ASCII characters (e.g. Chinese text in error messages from some providers). Re-encode non-ASCII header values via UTF-8→latin-1 to preserve the raw bytes in a form httpx can accept. --- litellm/llms/custom_httpx/aiohttp_transport.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/litellm/llms/custom_httpx/aiohttp_transport.py b/litellm/llms/custom_httpx/aiohttp_transport.py index 132191c946c..85a8033c20b 100644 --- a/litellm/llms/custom_httpx/aiohttp_transport.py +++ b/litellm/llms/custom_httpx/aiohttp_transport.py @@ -339,9 +339,23 @@ class LiteLLMAiohttpTransport(AiohttpTransport): # Re-raise if it's a different RuntimeError raise + # Sanitize response headers: aiohttp decodes header values as UTF-8 + # strings, but httpx.Headers internally calls .encode("ascii") which + # raises UnicodeEncodeError on non-ASCII values (e.g. Chinese characters). + # Re-encode via latin-1 to preserve the raw bytes for httpx. + sanitized_headers = [] + for key, value in response.headers.items(): + try: + value.encode("ascii") + sanitized_headers.append((key, value)) + except UnicodeEncodeError: + sanitized_headers.append( + (key, value.encode("utf-8").decode("latin-1")) + ) + return httpx.Response( status_code=response.status, - headers=response.headers, + headers=sanitized_headers, stream=AiohttpResponseStream(response), request=request, )