From 0dbeb5634649b4d35fdeb1eaa3cd49d237a49536 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Mon, 12 Jan 2026 18:28:29 -0800 Subject: [PATCH] Simplify Key Generate Permission Error --- .../organisms/create_key_button.tsx | 4 +- .../src/components/organisms/utils.test.ts | 146 ++++++++++++++++++ .../src/components/organisms/utils.ts | 56 +++++++ 3 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 ui/litellm-dashboard/src/components/organisms/utils.test.ts create mode 100644 ui/litellm-dashboard/src/components/organisms/utils.ts diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx index f05f1c4183..90ed9a62cc 100644 --- a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx +++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx @@ -38,6 +38,7 @@ import { } from "../networking"; import NumericalInput from "../shared/numerical_input"; import VectorStoreSelector from "../vector_store_management/VectorStoreSelector"; +import { simplifyKeyGenerateError } from "./utils"; const { Option } = Select; @@ -406,7 +407,8 @@ const CreateKey: React.FC = ({ team, teams, data, addKey }) => { localStorage.removeItem("userData" + userID); } catch (error) { console.log("error in create key:", error); - NotificationsManager.fromBackend(`Error creating the key: ${error}`); + const simplifiedError = simplifyKeyGenerateError(error); + NotificationsManager.fromBackend(simplifiedError); } }; diff --git a/ui/litellm-dashboard/src/components/organisms/utils.test.ts b/ui/litellm-dashboard/src/components/organisms/utils.test.ts new file mode 100644 index 0000000000..df653003a9 --- /dev/null +++ b/ui/litellm-dashboard/src/components/organisms/utils.test.ts @@ -0,0 +1,146 @@ +import { describe, expect, it } from "vitest"; +import { simplifyKeyGenerateError } from "./utils"; + +describe("simplifyKeyGenerateError", () => { + const expectedSimplifiedMessage = + "Team member does not have permission to generate key for this team. Ask your proxy admin to configure the team member permission settings."; + + describe("when error is NOT related to /key/generate", () => { + it("should return the original error message for generic errors", () => { + const error = "Some random error"; + const result = simplifyKeyGenerateError(error); + expect(result).toBe("Error creating the key: Some random error"); + }); + + it("should return the original error message for other endpoint errors", () => { + const error = "Error: Failed to fetch /key/list"; + const result = simplifyKeyGenerateError(error); + expect(result).toBe("Error creating the key: Error: Failed to fetch /key/list"); + }); + + it("should handle Error objects for non-/key/generate errors", () => { + const error = new Error("Database connection failed"); + const result = simplifyKeyGenerateError(error); + expect(result).toBe("Error creating the key: Error: Database connection failed"); + }); + }); + + describe("when error is related to /key/generate team member permission error", () => { + it("should simplify JSON error with team_member_permission_error", () => { + const error = JSON.stringify({ + error: { + message: + "Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE. You only have access to the following endpoints: ['/key/info', '/key/health'] for team 60f6c0db-3ed9-4112-a2ef-8d838b2c8679. To create keys for this team, please ask your proxy admin to check the team member permission settings and update the settings to allow team member users to create keys.", + type: "team_member_permission_error", + param: "/key/generate", + code: "401", + }, + }); + const result = simplifyKeyGenerateError(error); + expect(result).toBe(expectedSimplifiedMessage); + }); + + it("should simplify error string containing /key/generate and team_member_permission_error", () => { + const error = + 'Error creating the key: {"error":{"message":"Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE. You only have access to the following endpoints: [\'/key/info\', \'/key/health\'] for team 60f6c0db-3ed9-4112-a2ef-8d838b2c8679. To create keys for this team, please ask your proxy admin to check the team member permission settings and update the settings to allow team member users to create keys.","type":"team_member_permission_error","param":"/key/generate","code":"401"}}'; + const result = simplifyKeyGenerateError(error); + expect(result).toBe(expectedSimplifiedMessage); + }); + + it("should simplify error with KeyManagementRoutes.KEY_GENERATE in message", () => { + const error = + "Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE. Ask your proxy admin to check the team member permission settings."; + const result = simplifyKeyGenerateError(error); + expect(result).toBe(expectedSimplifiedMessage); + }); + + it("should handle nested error object structure", () => { + const error = { + error: { + message: + "Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE. You only have access to the following endpoints: ['/key/info', '/key/health'].", + type: "team_member_permission_error", + }, + }; + const result = simplifyKeyGenerateError(error); + expect(result).toBe(expectedSimplifiedMessage); + }); + + it("should handle error with team_member_permission_error type in string", () => { + const error = + 'Some prefix {"error":{"type":"team_member_permission_error","message":"Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE"}} some suffix'; + const result = simplifyKeyGenerateError(error); + expect(result).toBe(expectedSimplifiedMessage); + }); + }); + + describe("when error is related to /key/generate but NOT a permission error", () => { + it("should return original error message for /key/generate validation errors", () => { + const error = "Invalid request to /key/generate: missing required field"; + const result = simplifyKeyGenerateError(error); + expect(result).toBe("Error creating the key: Invalid request to /key/generate: missing required field"); + }); + + it("should return original error message for /key/generate server errors", () => { + const error = JSON.stringify({ + error: { + message: "Internal server error occurred while processing /key/generate", + type: "server_error", + code: "500", + }, + }); + const result = simplifyKeyGenerateError(error); + expect(result).toBe(`Error creating the key: ${error}`); + }); + }); + + describe("edge cases", () => { + it("should handle malformed JSON gracefully", () => { + const error = + '{"error":{"message":"Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE", invalid json'; + const result = simplifyKeyGenerateError(error); + // Should still detect the permission error from the string content + expect(result).toBe(expectedSimplifiedMessage); + }); + + it("should handle empty string", () => { + const error = ""; + const result = simplifyKeyGenerateError(error); + expect(result).toBe("Error creating the key: "); + }); + + it("should handle null", () => { + const error = null; + const result = simplifyKeyGenerateError(error); + expect(result).toBe("Error creating the key: null"); + }); + + it("should handle undefined", () => { + const error = undefined; + const result = simplifyKeyGenerateError(error); + expect(result).toBe("Error creating the key: undefined"); + }); + + it("should handle Error object with /key/generate permission error", () => { + const error = new Error( + '{"error":{"message":"Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE","type":"team_member_permission_error"}}', + ); + const result = simplifyKeyGenerateError(error); + expect(result).toBe(expectedSimplifiedMessage); + }); + + it("should handle error with multiple JSON objects", () => { + const error = + 'Prefix {"error":{"message":"Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE","type":"team_member_permission_error"}} suffix {"other":"data"}'; + const result = simplifyKeyGenerateError(error); + expect(result).toBe(expectedSimplifiedMessage); + }); + + it("should handle error message without explicit team_member_permission_error type but with permission text", () => { + const error = + "Team member does not have permissions for endpoint: KeyManagementRoutes.KEY_GENERATE. Please contact admin."; + const result = simplifyKeyGenerateError(error); + expect(result).toBe(expectedSimplifiedMessage); + }); + }); +}); diff --git a/ui/litellm-dashboard/src/components/organisms/utils.ts b/ui/litellm-dashboard/src/components/organisms/utils.ts new file mode 100644 index 0000000000..c08fb10e8a --- /dev/null +++ b/ui/litellm-dashboard/src/components/organisms/utils.ts @@ -0,0 +1,56 @@ +/** + * Helper function to simplify /key/generate permission errors + * Extracts a user-friendly error message from team member permission errors + * @param error - The error object or message + * @returns A simplified error message string + */ +export const simplifyKeyGenerateError = (error: any): string => { + // Handle plain objects by stringifying them first + let errorString: string; + if (error && typeof error === "object" && !(error instanceof Error)) { + errorString = JSON.stringify(error); + } else { + errorString = String(error); + } + + // Check if this is a /key/generate team member permission error + if (!errorString.includes("/key/generate") && !errorString.includes("KeyManagementRoutes.KEY_GENERATE")) { + return `Error creating the key: ${error}`; + } + + // Try to parse JSON if the message contains JSON or extract from object + let errorMessage = errorString; + try { + // If error is already an object, extract message directly + if (error && typeof error === "object" && !(error instanceof Error)) { + const errorObj = error?.error || error; + if (errorObj?.message) { + errorMessage = errorObj.message; + } + } else { + // Try to parse JSON from string + const jsonMatch = errorString.match(/\{[\s\S]*\}/); + if (jsonMatch) { + const parsedError = JSON.parse(jsonMatch[0]); + const errorObj = parsedError?.error || parsedError; + if (errorObj?.message) { + errorMessage = errorObj.message; + } + } + } + } catch (e) { + // If parsing fails, use the original message + } + + // Check if this is a team member permission error + if ( + errorString.includes("team_member_permission_error") || + errorMessage.includes("Team member does not have permissions") + ) { + // Return the simplified message + return "Team member does not have permission to generate key for this team. Ask your proxy admin to configure the team member permission settings."; + } + + // If it's not a permission error, return the original error message + return `Error creating the key: ${error}`; +};