Skip to content

Commit f694823

Browse files
tombiiclaude
andcommitted
fix: also normalize tool call IDs in async_transform_request, hoist regex to module level
Addresses review feedback on #22318: - `async_transform_request` base-class path was missing the `_normalize_tool_call_ids()` call, leaving async callers exposed to the same 400 BadRequestError from strict providers (e.g. Mistral) - Hoist `_VALID_TOOL_CALL_ID_RE` to module level to avoid recompiling the regex on every request Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 906c6b8 commit f694823

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

litellm/llms/openai/chat/gpt_transformation.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
import httpx
2424

2525
import litellm
26+
27+
# Pre-compiled pattern for validating OpenAI-compatible tool call IDs.
28+
# Strict providers (e.g. Mistral) reject IDs that don't match this.
29+
_VALID_TOOL_CALL_ID_RE = re.compile(r"^[a-zA-Z0-9]{1,64}$")
2630
from litellm.litellm_core_utils.core_helpers import map_finish_reason
2731
from litellm.litellm_core_utils.llm_response_utils.convert_dict_to_response import (
2832
_extract_reasoning_content,
@@ -460,6 +464,7 @@ async def async_transform_request(
460464
transformed_messages = await self._transform_messages(
461465
messages=messages, model=model, is_async=True
462466
)
467+
transformed_messages = self._normalize_tool_call_ids(transformed_messages)
463468
transformed_messages, tools = (
464469
self.remove_cache_control_flag_from_messages_and_tools(
465470
model=model,
@@ -504,8 +509,6 @@ def _normalize_tool_call_ids(
504509
IDs that already satisfy ``^[a-zA-Z0-9]{1,64}$`` are left unchanged so
505510
there is zero overhead for well-behaved providers.
506511
"""
507-
_VALID_TOOL_CALL_ID = re.compile(r"^[a-zA-Z0-9]{1,64}$")
508-
509512
def _remap_id(original: str, mapping: Dict[str, str]) -> str:
510513
if original not in mapping:
511514
digest = hashlib.md5(original.encode()).hexdigest()[:9]
@@ -523,7 +526,7 @@ def _remap_id(original: str, mapping: Dict[str, str]) -> str:
523526
tc_id = (
524527
tc.get("id") if isinstance(tc, dict) else getattr(tc, "id", None)
525528
)
526-
if tc_id and not _VALID_TOOL_CALL_ID.match(tc_id):
529+
if tc_id and not _VALID_TOOL_CALL_ID_RE.match(tc_id):
527530
_remap_id(tc_id, id_mapping)
528531

529532
if not id_mapping:

0 commit comments

Comments
 (0)