From 74ebc0606953402da44ff1cefb558d90c5695f55 Mon Sep 17 00:00:00 2001 From: mateo Date: Tue, 27 Oct 2026 20:05:45 +0000 Subject: [PATCH] fix(gemini): keep the placeholder resend inside the cache rebuild so either rejection order ends in an accepted body Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../rejected_thought_signature_retry.py | 14 ++++++---- .../vertex_and_google_ai_studio_gemini.py | 28 ++++++------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/litellm/llms/vertex_ai/gemini/rejected_thought_signature_retry.py b/litellm/llms/vertex_ai/gemini/rejected_thought_signature_retry.py index 96aead87f61..ae51efb2b34 100644 --- a/litellm/llms/vertex_ai/gemini/rejected_thought_signature_retry.py +++ b/litellm/llms/vertex_ai/gemini/rejected_thought_signature_retry.py @@ -64,27 +64,29 @@ async def post_with_accepted_thought_signatures_async( body: RequestBody, post: Callable[[RequestBody], Awaitable[Sent]], log_request: Callable[[RequestBody], None], -) -> Sent: +) -> tuple[RequestBody, Sent]: + """Innermost retry around the raw post, so a cache rebuild (which re-transforms the messages and brings + the rejected signatures back) is itself wrapped by it. Returns the body the backend accepted.""" try: - return await post(body) + return body, await post(body) except (httpx.HTTPStatusError, BaseLLMException) as error: resend_body: Final = _resend_body(body, error) if resend_body is None: raise log_request(resend_body) - return await post(resend_body) + return resend_body, await post(resend_body) def post_with_accepted_thought_signatures_sync( body: RequestBody, post: Callable[[RequestBody], Sent], log_request: Callable[[RequestBody], None], -) -> Sent: +) -> tuple[RequestBody, Sent]: try: - return post(body) + return body, post(body) except (httpx.HTTPStatusError, BaseLLMException) as error: resend_body: Final = _resend_body(body, error) if resend_body is None: raise log_request(resend_body) - return post(resend_body) + return resend_body, post(resend_body) diff --git a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py index 4ad9b1b973b..53d412c7300 100644 --- a/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py +++ b/litellm/llms/vertex_ai/gemini/vertex_and_google_ai_studio_gemini.py @@ -3476,12 +3476,8 @@ class VertexLLM(VertexBase): async def post(body: RequestBody) -> ModelResponseIterator: return await open_stream(client=client, data=json.dumps(body), request_body=body) - post_with_fresh_cache: Final = partial( - post_with_fresh_cache_async, rebuild=rebuild, post=post, log_request=log_request - ) - return ( - await post_with_accepted_thought_signatures_async(request_body, post_with_fresh_cache, log_request) - )[1] + accepted: Final = partial(post_with_accepted_thought_signatures_async, post=post, log_request=log_request) + return (await post_with_fresh_cache_async(request_body, rebuild, accepted, log_request))[1][1] streaming_response: Final = CustomStreamWrapper( completion_stream=None, @@ -3605,12 +3601,8 @@ class VertexLLM(VertexBase): ) return response - post_with_fresh_cache: Final = partial( - post_with_fresh_cache_async, rebuild=rebuild, post=post, log_request=log_request - ) - sent_body, first_response = await post_with_accepted_thought_signatures_async( - request_body, post_with_fresh_cache, log_request - ) + accepted: Final = partial(post_with_accepted_thought_signatures_async, post=post, log_request=log_request) + _, (sent_body, first_response) = await post_with_fresh_cache_async(request_body, rebuild, accepted, log_request) return _transform_long_decode_hops( model=model, hops=await collect_hops_async(parse_body(first_response), sent_body, post), @@ -3786,10 +3778,10 @@ class VertexLLM(VertexBase): def post(body: RequestBody) -> ModelResponseIterator: return open_stream(client=client, data=json.dumps(body), request_body=body) - post_with_fresh_cache: Final = partial( - post_with_fresh_cache_sync, rebuild=rebuild, post=post, log_request=log_request + accepted: Final = partial( + post_with_accepted_thought_signatures_sync, post=post, log_request=log_request ) - return post_with_accepted_thought_signatures_sync(data, post_with_fresh_cache, log_request)[1] + return post_with_fresh_cache_sync(data, rebuild, accepted, log_request)[1][1] streaming_response: Final = CustomStreamWrapper( completion_stream=None, @@ -3833,10 +3825,8 @@ class VertexLLM(VertexBase): ) return response - post_with_fresh_cache: Final = partial( - post_with_fresh_cache_sync, rebuild=rebuild, post=post, log_request=log_request - ) - sent_body, first_response = post_with_accepted_thought_signatures_sync(data, post_with_fresh_cache, log_request) + accepted: Final = partial(post_with_accepted_thought_signatures_sync, post=post, log_request=log_request) + _, (sent_body, first_response) = post_with_fresh_cache_sync(data, rebuild, accepted, log_request) return _transform_long_decode_hops( model=model, hops=collect_hops_sync(parse_body(first_response), sent_body, post),