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)."""