mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-14 23:21:35 +00:00
Router.log_retry used to copy the failed attempt's kwargs and metadata into metadata.previous_models. Nothing downstream read those copies, but they carried client credentials into spend logs and grew the payload on every retry. Each attempt now leaves a flat record (model group, deployment id, exception type and string, attempt number), which drops RETRY_BREADCRUMB_EXCLUDED_KWARGS and the per-retry credential masking. num_retries_per_request was enforced from len(previous_models), which only looked at the metadata bucket and never exceeded four records. The sync and async client wrappers and the Rust lifecycle guard now read attempted_retries from whichever metadata bucket the call carries. Resolves LIT-7505 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
30 lines
1 KiB
Python
30 lines
1 KiB
Python
from typing import Final
|
|
|
|
import pytest
|
|
|
|
import litellm
|
|
from litellm.rust_bridge.lifecycle import check_limits
|
|
|
|
|
|
@pytest.mark.parametrize("metadata_key", ["metadata", "litellm_metadata"])
|
|
@pytest.mark.parametrize(
|
|
"cap, attempted_retries, refused",
|
|
[(5, 5, True), (5, 4, False), (0, 0, False), (0, 1, True)],
|
|
ids=[
|
|
"cap-above-four-reached",
|
|
"cap-above-four-not-reached",
|
|
"first-attempt-passes-cap-of-zero",
|
|
"cap-of-zero-refuses-first-retry",
|
|
],
|
|
)
|
|
def test_check_limits_reads_attempted_retries(
|
|
monkeypatch: pytest.MonkeyPatch, metadata_key: str, cap: int, attempted_retries: int, refused: bool
|
|
) -> None:
|
|
monkeypatch.setattr(litellm, "num_retries_per_request", cap)
|
|
monkeypatch.setattr(litellm, "max_budget", None)
|
|
kwargs: Final = {"model": "mistral/mistral-ocr-latest", metadata_key: {"attempted_retries": attempted_retries}}
|
|
if refused:
|
|
with pytest.raises(RuntimeError, match="Max retries per request hit!"):
|
|
check_limits(kwargs)
|
|
else:
|
|
check_limits(kwargs)
|