diff --git a/ui/litellm-dashboard/src/components/model_dashboard/HealthCheckComponent.test.tsx b/ui/litellm-dashboard/src/components/model_dashboard/HealthCheckComponent.test.tsx
index 84c9f0a0948..48e325baa3d 100644
--- a/ui/litellm-dashboard/src/components/model_dashboard/HealthCheckComponent.test.tsx
+++ b/ui/litellm-dashboard/src/components/model_dashboard/HealthCheckComponent.test.tsx
@@ -92,56 +92,140 @@ describe("HealthCheckComponent", () => {
expect(mockIndividualModelHealthCheckCall).not.toHaveBeenCalledWith("token-123", "gpt-4");
});
- it("should key health status by model id and show status from latest_health_checks by model_id", async () => {
- const modelData = {
- data: [
- {
- model_name: "gpt-4",
- model_info: { id: "id-alpha" },
- litellm_model_name: "gpt-4",
- },
- {
- model_name: "gpt-4",
- model_info: { id: "id-beta" },
- litellm_model_name: "gpt-4",
- },
- ],
- };
+ describe("latest_health_checks keyed by model id", () => {
+ it("should show status from latest_health_checks when keys match model ids", async () => {
+ const modelData = {
+ data: [
+ {
+ model_name: "gpt-4",
+ model_info: { id: "id-alpha" },
+ litellm_model_name: "gpt-4",
+ },
+ {
+ model_name: "gpt-4",
+ model_info: { id: "id-beta" },
+ litellm_model_name: "gpt-4",
+ },
+ ],
+ };
- mockLatestHealthChecksCall.mockResolvedValue({
- latest_health_checks: {
- "id-alpha": {
- status: "healthy",
- checked_at: "2024-01-15T10:00:00Z",
- error_message: null,
+ mockLatestHealthChecksCall.mockResolvedValue({
+ latest_health_checks: {
+ "id-alpha": {
+ status: "healthy",
+ checked_at: "2024-01-15T10:00:00Z",
+ error_message: null,
+ },
+ "id-beta": {
+ status: "unhealthy",
+ checked_at: "2024-01-15T10:05:00Z",
+ error_message: "Connection failed",
+ },
},
- "id-beta": {
- status: "unhealthy",
- checked_at: "2024-01-15T10:05:00Z",
- error_message: "Connection failed",
- },
- },
+ });
+
+ await act(async () => {
+ render(
+ ,
+ );
+ });
+ await act(async () => {
+ await new Promise((r) => setTimeout(r, 0));
+ });
+
+ expect(mockLatestHealthChecksCall).toHaveBeenCalledWith("token");
+ const healthyBadges = screen.getAllByText("healthy");
+ const unhealthyBadges = screen.getAllByText("unhealthy");
+ expect(healthyBadges.length).toBeGreaterThanOrEqual(1);
+ expect(unhealthyBadges.length).toBeGreaterThanOrEqual(1);
});
- await act(async () => {
- render(
- ,
- );
+ it("should skip latest_health_checks entries whose key is not a known model id", async () => {
+ const modelData = {
+ data: [
+ {
+ model_name: "gpt-4",
+ model_info: { id: "current-model-id" },
+ litellm_model_name: "gpt-4",
+ },
+ ],
+ };
+
+ mockLatestHealthChecksCall.mockResolvedValue({
+ latest_health_checks: {
+ "current-model-id": {
+ status: "healthy",
+ checked_at: "2024-01-15T10:00:00Z",
+ error_message: null,
+ },
+ "deleted-or-unknown-id": {
+ status: "unhealthy",
+ checked_at: "2024-01-15T10:05:00Z",
+ error_message: "Stale entry",
+ },
+ },
+ });
+
+ await act(async () => {
+ render(
+ ,
+ );
+ });
+ await act(async () => {
+ await new Promise((r) => setTimeout(r, 0));
+ });
+
+ expect(screen.getByText("healthy")).toBeInTheDocument();
+ expect(screen.queryByText("unhealthy")).not.toBeInTheDocument();
});
- await act(async () => {
- await new Promise((r) => setTimeout(r, 0));
- });
+ it("should not apply status when latest_health_checks key is model name not model id", async () => {
+ const modelData = {
+ data: [
+ {
+ model_name: "gpt-4",
+ model_info: { id: "model-id-123" },
+ litellm_model_name: "gpt-4",
+ },
+ ],
+ };
- expect(mockLatestHealthChecksCall).toHaveBeenCalledWith("token");
- const healthyBadges = screen.getAllByText("healthy");
- const unhealthyBadges = screen.getAllByText("unhealthy");
- expect(healthyBadges.length).toBeGreaterThanOrEqual(1);
- expect(unhealthyBadges.length).toBeGreaterThanOrEqual(1);
+ mockLatestHealthChecksCall.mockResolvedValue({
+ latest_health_checks: {
+ "gpt-4": {
+ status: "healthy",
+ checked_at: "2024-01-15T10:00:00Z",
+ error_message: null,
+ },
+ },
+ });
+
+ await act(async () => {
+ render(
+ ,
+ );
+ });
+ await act(async () => {
+ await new Promise((r) => setTimeout(r, 0));
+ });
+
+ expect(screen.queryByText("healthy")).not.toBeInTheDocument();
+ expect(screen.getByText("none")).toBeInTheDocument();
+ });
});
});
diff --git a/ui/litellm-dashboard/src/components/model_dashboard/HealthCheckComponent.tsx b/ui/litellm-dashboard/src/components/model_dashboard/HealthCheckComponent.tsx
index b4bb1019dd6..db71733b5ba 100644
--- a/ui/litellm-dashboard/src/components/model_dashboard/HealthCheckComponent.tsx
+++ b/ui/litellm-dashboard/src/components/model_dashboard/HealthCheckComponent.tsx
@@ -85,31 +85,16 @@ const HealthCheckComponent: React.FC = ({
latestHealthChecks.latest_health_checks &&
typeof latestHealthChecks.latest_health_checks === "object"
) {
- Object.entries(latestHealthChecks.latest_health_checks).forEach(([key, checkData]: [string, any]) => {
+ Object.entries(latestHealthChecks.latest_health_checks).forEach(([modelId, checkData]: [string, any]) => {
if (!checkData) return;
- let targetModelId: string | null = null;
+ // Key is model_id from the backend (guaranteed by DB schema)
+ const modelExists = modelData.data.some((m: any) => m.model_info?.id === modelId);
+ if (!modelExists) return;
- // The key is model_id from the backend; fallback to matching by model_name for legacy data
- const modelByIdMatch = modelData.data.find((m: any) => m.model_info && m.model_info.id === key);
- if (modelByIdMatch) {
- targetModelId = modelByIdMatch.model_info.id;
- } else {
- const directModelMatch = modelData.data.find((m: any) => m.model_name === key);
- if (directModelMatch?.model_info?.id) {
- targetModelId = directModelMatch.model_info.id;
- } else if (checkData.model_name) {
- const modelByNameInData = modelData.data.find((m: any) => m.model_name === checkData.model_name);
- if (modelByNameInData?.model_info?.id) {
- targetModelId = modelByNameInData.model_info.id;
- }
- }
- }
+ const fullError = checkData.error_message || undefined;
- if (targetModelId) {
- const fullError = checkData.error_message || undefined;
-
- healthStatusMap[targetModelId] = {
+ healthStatusMap[modelId] = {
status: checkData.status || "unknown",
lastCheck: checkData.checked_at ? new Date(checkData.checked_at).toLocaleString() : "None",
lastSuccess:
@@ -123,7 +108,6 @@ const HealthCheckComponent: React.FC = ({
fullError: fullError,
successResponse: checkData.status === "healthy" ? checkData : undefined,
};
- }
});
}
} catch (healthError) {