From 8c59d2550b39b2212e5e4c8526a1e5ba92469031 Mon Sep 17 00:00:00 2001 From: Paolo Antinori Date: Fri, 18 Sep 2026 19:56:59 +0200 Subject: [PATCH] fix(router): narrow the optional map before subscripting; cover the warning path --- litellm/router.py | 7 +++++-- .../router_unit_tests/test_router_finish_reason_failure.py | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/litellm/router.py b/litellm/router.py index 87d3d95d646..7857eb70d92 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -8708,9 +8708,12 @@ class Router: def _finish_reason_failure_error(self, model: str, reason: str) -> Exception: """Build the exception instance configured for a mapped finish reason.""" - exception_name: Final = self.treat_finish_reason_as_failure[reason] - exception_cls: Final = getattr(litellm, exception_name) message: Final = f"Response finished with reason '{reason}' (treat_finish_reason_as_failure)." + finish_reason_map: Final = self.treat_finish_reason_as_failure + if finish_reason_map is None: + return litellm.APIError(status_code=500, message=message, llm_provider="", model=model) + exception_name: Final = finish_reason_map[reason] + exception_cls: Final = getattr(litellm, exception_name) if exception_name == "APIError": return exception_cls(status_code=500, message=message, llm_provider="", model=model) return exception_cls(message=message, llm_provider="", model=model) diff --git a/tests/router_unit_tests/test_router_finish_reason_failure.py b/tests/router_unit_tests/test_router_finish_reason_failure.py index 5c9fd639313..17e728e992e 100644 --- a/tests/router_unit_tests/test_router_finish_reason_failure.py +++ b/tests/router_unit_tests/test_router_finish_reason_failure.py @@ -175,6 +175,12 @@ def test_unknown_exception_name_raises_at_construction(): Router(model_list=[], treat_finish_reason_as_failure={"x": "NotAnException"}) +def test_healthy_terminal_key_warns_at_construction(capsys: pytest.CaptureFixture): + Router(model_list=[], treat_finish_reason_as_failure={"stop": "RateLimitError"}) + logged = capsys.readouterr().err + capsys.readouterr().out + assert "healthy terminal reasons" in logged + + @pytest.mark.asyncio async def test_mapped_finish_reason_helpers_direct(monkeypatch: MonkeyPatch): """Direct coverage of the knob helpers (the router code-coverage check matches by name)."""