fix(gemini): map any count_tokens translation failure to a 400 error response

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Devin AI 2026-09-24 23:38:12 +00:00
parent e3713c767f
commit ff8491d610
2 changed files with 10 additions and 3 deletions

View file

@ -442,7 +442,7 @@ def build_count_tokens_payload(
if _has_anthropic_shape(system=system, tools=tools, messages=messages):
return _build_anthropic_payload(model=model, messages=messages, system=system, tools=tools)
return _build_openai_payload(model=model, messages=messages, system=system, tools=tools)
except (KeyError, TypeError, ValueError) as e:
except Exception as e: # noqa: BLE001 # translation is pure; any failure is untranslatable input
return InvalidCountTokensRequest(message=f"Invalid token count request: {e!r}")

View file

@ -259,14 +259,21 @@ class TestGoogleAIStudioTokenCounter:
assert result.error_message is not None
@pytest.mark.asyncio
async def test_count_tokens_translation_error_falls_back(self):
@pytest.mark.parametrize(
"bad_messages",
[
[{"role": "tool", "content": "orphaned result", "tool_call_id": "missing-call"}],
[{"role": "user", "content": [{"type": "text", "text": 123}]}],
],
)
async def test_count_tokens_translation_error_falls_back(self, bad_messages):
"""Malformed message shapes surface as a 400 error TokenCountResponse so
the proxy falls back instead of 500ing."""
token_counter = GoogleAIStudioTokenCounter()
result = await token_counter.count_tokens(
model_to_use="gemini-2.5-flash",
messages=[{"role": "user", "content": [{"type": "text", "text": 123}]}],
messages=bad_messages,
contents=None,
deployment={"litellm_params": {"api_key": "test-key"}},
request_model="gemini/gemini-2.5-flash",