diff --git a/ui/litellm-dashboard/src/app/page.tsx b/ui/litellm-dashboard/src/app/page.tsx index c3ff7c4c70..1750328129 100644 --- a/ui/litellm-dashboard/src/app/page.tsx +++ b/ui/litellm-dashboard/src/app/page.tsx @@ -342,6 +342,7 @@ export default function CreateKeyPage() { setTeams={setTeams} searchParams={searchParams} accessToken={accessToken} + userID={userID} showSSOBanner={showSSOBanner} premiumUser={premiumUser} proxySettings={proxySettings} diff --git a/ui/litellm-dashboard/src/components/SCIM.tsx b/ui/litellm-dashboard/src/components/SCIM.tsx index 4f85f40e01..c6a66b8f40 100644 --- a/ui/litellm-dashboard/src/components/SCIM.tsx +++ b/ui/litellm-dashboard/src/components/SCIM.tsx @@ -20,6 +20,7 @@ import { ExclamationCircleOutlined, PlusCircleOutlined } from "@ant-design/icons"; +import { parseErrorMessage } from "./shared/errorUtils"; interface SCIMConfigProps { accessToken: string | null; @@ -67,9 +68,9 @@ const SCIMConfig: React.FC = ({ accessToken, userID, proxySetti const response = await keyCreateCall(accessToken, userID, formData); setTokenData(response); message.success("SCIM token created successfully"); - } catch (error) { + } catch (error: any) { console.error("Error creating SCIM token:", error); - message.error("Failed to create SCIM token"); + message.error("Failed to create SCIM token: " + parseErrorMessage(error)); } finally { setIsCreatingToken(false); } diff --git a/ui/litellm-dashboard/src/components/admins.tsx b/ui/litellm-dashboard/src/components/admins.tsx index af22fbb23c..2ea3e74bcb 100644 --- a/ui/litellm-dashboard/src/components/admins.tsx +++ b/ui/litellm-dashboard/src/components/admins.tsx @@ -48,6 +48,7 @@ import SCIMConfig from "./SCIM"; interface AdminPanelProps { searchParams: any; accessToken: string | null; + userID: string | null; setTeams: React.Dispatch>; showSSOBanner: boolean; premiumUser: boolean; @@ -72,6 +73,7 @@ import { const AdminPanel: React.FC = ({ searchParams, accessToken, + userID, showSSOBanner, premiumUser, proxySettings, @@ -639,7 +641,7 @@ const AdminPanel: React.FC = ({ 0 ? admins[0].user_id : null} + userID={userID} proxySettings={proxySettings} /> diff --git a/ui/litellm-dashboard/src/components/shared/errorUtils.tsx b/ui/litellm-dashboard/src/components/shared/errorUtils.tsx new file mode 100644 index 0000000000..68b370771e --- /dev/null +++ b/ui/litellm-dashboard/src/components/shared/errorUtils.tsx @@ -0,0 +1,44 @@ +/** + * Extracts a user-friendly error message from various error formats + * @param {any} error - The error object or message + * @returns {string} - A clean error message + */ +export const parseErrorMessage = (error: any): string => { + if (!error) return "An unknown error occurred"; + + // If error is already a string, return it + if (typeof error === 'string') return error; + + // If error has a message property, check if it's a JSON string + if (error.message) { + try { + // Try to parse the error message as JSON + const parsedError = JSON.parse(error.message); + + // Handle common nested error structures + if (parsedError.error && parsedError.error.message) { + return parsedError.error.message; + } + + // If parsed successfully but no nested message found, stringify it nicely + return typeof parsedError === 'string' ? parsedError : JSON.stringify(parsedError, null, 2); + } catch (e) { + // If parsing fails, just return the original message + return error.message; + } + } + + // If error has a response with data + if (error.response && error.response.data) { + if (typeof error.response.data === 'string') return error.response.data; + if (error.response.data.message) return error.response.data.message; + if (error.response.data.error) { + return typeof error.response.data.error === 'string' + ? error.response.data.error + : error.response.data.error.message || JSON.stringify(error.response.data.error); + } + } + + // Fallback to stringifying the error + return String(error); +}; \ No newline at end of file