Skip to content

Commit 416cade

Browse files
committed
fix(router): resolve_llm_passthrough_timeout respects stream_timeout
resolve_llm_passthrough_timeout (added by upstream PR BerriAI#30266) only checked timeout/request_timeout, so streaming Anthropic /v1/messages calls (routed through _ageneric_api_call_with_fallbacks) stopped honoring stream_timeout precedence, unlike the router's own _get_stream_timeout/_get_timeout used by other call paths. Threads stream and router_stream_timeout through so streaming requests check stream_timeout first, mirroring existing router semantics.
1 parent 4276287 commit 416cade

3 files changed

Lines changed: 61 additions & 0 deletions

File tree

litellm/passthrough/timeout_utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,29 @@ def resolve_llm_passthrough_timeout(
3434
kwargs: Optional[dict] = None,
3535
litellm_params: Optional[dict] = None,
3636
router_timeout: Optional[float] = None,
37+
stream: bool = False,
38+
router_stream_timeout: Optional[float] = None,
3739
) -> float:
3840
"""
3941
Resolve upstream httpx timeout for SDK native passthrough (e.g. Bedrock /converse).
4042
4143
Precedence: kwargs timeout/request_timeout -> litellm_params timeout/request_timeout
4244
-> router_timeout -> general_settings.pass_through_request_timeout -> 600s default.
45+
46+
For streaming requests, kwargs/litellm_params stream_timeout and router_stream_timeout
47+
are checked ahead of the rest of the chain, mirroring Router._get_stream_timeout.
4348
"""
4449
kwargs = kwargs or {}
4550
litellm_params = litellm_params or {}
4651

52+
if stream:
53+
for source in (kwargs, litellm_params):
54+
val = source.get("stream_timeout")
55+
if val is not None:
56+
return float(val)
57+
if router_stream_timeout is not None:
58+
return float(router_stream_timeout)
59+
4760
for source in (kwargs, litellm_params):
4861
for key in ("timeout", "request_timeout"):
4962
val = source.get(key)

litellm/router.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3036,6 +3036,8 @@ def _update_kwargs_with_deployment(
30363036
kwargs=kwargs,
30373037
litellm_params=deployment["litellm_params"],
30383038
router_timeout=_router_timeout,
3039+
stream=bool(kwargs.get("stream", False)),
3040+
router_stream_timeout=self.stream_timeout,
30393041
)
30403042
else:
30413043
kwargs["timeout"] = self._get_timeout(kwargs=kwargs, data=deployment["litellm_params"])

tests/test_litellm/proxy/pass_through_endpoints/test_pass_through_endpoints.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,52 @@ def test_resolve_llm_passthrough_timeout_precedence():
974974
assert resolve_llm_passthrough_timeout() == 6.0
975975

976976

977+
def test_resolve_llm_passthrough_timeout_stream_timeout_precedence():
978+
# stream_timeout wins over timeout for streaming requests, mirroring Router._get_stream_timeout
979+
assert (
980+
resolve_llm_passthrough_timeout(
981+
kwargs={"stream_timeout": 1, "timeout": 30},
982+
stream=True,
983+
)
984+
== 1.0
985+
)
986+
# non-streaming requests ignore stream_timeout entirely
987+
assert (
988+
resolve_llm_passthrough_timeout(
989+
kwargs={"stream_timeout": 1, "timeout": 30},
990+
stream=False,
991+
)
992+
== 30.0
993+
)
994+
# litellm_params stream_timeout is checked when kwargs has none
995+
assert (
996+
resolve_llm_passthrough_timeout(
997+
kwargs={"timeout": 30},
998+
litellm_params={"stream_timeout": 2},
999+
stream=True,
1000+
)
1001+
== 2.0
1002+
)
1003+
# router_stream_timeout is a last resort before falling back to the non-stream chain
1004+
assert (
1005+
resolve_llm_passthrough_timeout(
1006+
router_timeout=30,
1007+
router_stream_timeout=5,
1008+
stream=True,
1009+
)
1010+
== 5.0
1011+
)
1012+
# no stream_timeout configured anywhere -> falls back to the non-stream chain
1013+
assert (
1014+
resolve_llm_passthrough_timeout(
1015+
kwargs={"timeout": 30},
1016+
router_stream_timeout=None,
1017+
stream=True,
1018+
)
1019+
== 30.0
1020+
)
1021+
1022+
9771023
@pytest.mark.asyncio
9781024
async def test_pass_through_request_uses_resolved_timeout():
9791025
with patch("litellm.proxy.proxy_server.proxy_logging_obj") as mock_proxy_logging:

0 commit comments

Comments
 (0)