Spaces:
Running
Running
Download apps/web/src/lib/error-utils.ts from Benaah/MicProtocol: direct link, hf CLI and curl.
- Browser
- Download file 4.34 kB
-
https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/apps/web/src/lib/error-utils.ts
- Command line
-
hf download hf://spaces/Benaah/MicProtocol/apps/web/src/lib/error-utils.ts
-
curl -L -o error-utils.ts https://huggingface.co/spaces/Benaah/MicProtocol/resolve/main/apps/web/src/lib/error-utils.ts
4.34 kB
| import { TRPCClientError } from "@trpc/client"; | |
| /** | |
| * Standard utility to parse errors from tRPC, HTTP responses, or native Error objects | |
| * and extract user-friendly messages, status codes, and field validation errors. | |
| */ | |
| export interface FormattedError { | |
| title: string; | |
| message: string; | |
| statusCode?: number; | |
| code?: string; | |
| requestId?: string; | |
| fieldErrors?: Record<string, string>; | |
| isNetworkError: boolean; | |
| isRateLimit: boolean; | |
| isAuthError: boolean; | |
| isForbidden: boolean; | |
| isNotFound: boolean; | |
| } | |
| export function parseError(error: unknown, fallbackMessage = "An unexpected error occurred"): FormattedError { | |
| let title = "Error"; | |
| let message = fallbackMessage; | |
| let statusCode: number | undefined; | |
| let code: string | undefined; | |
| let requestId: string | undefined; | |
| let fieldErrors: Record<string, string> | undefined; | |
| let isNetworkError = false; | |
| if (!error) { | |
| return { | |
| title, | |
| message, | |
| isNetworkError: false, | |
| isRateLimit: false, | |
| isAuthError: false, | |
| isForbidden: false, | |
| isNotFound: false, | |
| }; | |
| } | |
| // Handle tRPC Client Error | |
| if (error instanceof TRPCClientError || (typeof error === "object" && error !== null && "data" in error)) { | |
| const trpcErr = error as any; | |
| code = trpcErr.data?.code; | |
| statusCode = trpcErr.data?.httpStatus; | |
| if (trpcErr.message) { | |
| message = trpcErr.message; | |
| } | |
| // Check for zod validation errors | |
| if (trpcErr.data?.zodError) { | |
| const zodData = trpcErr.data.zodError; | |
| if (typeof zodData === "object" && zodData.fieldErrors) { | |
| fieldErrors = {}; | |
| for (const [field, msgs] of Object.entries(zodData.fieldErrors)) { | |
| if (Array.isArray(msgs) && msgs.length > 0) { | |
| fieldErrors[field] = msgs[0] as string; | |
| } | |
| } | |
| message = "Please check the highlighted fields and try again."; | |
| title = "Validation Failed"; | |
| } else if (typeof zodData === "string") { | |
| try { | |
| const parsed = JSON.parse(zodData); | |
| if (Array.isArray(parsed) && parsed.length > 0) { | |
| message = parsed[0].message || message; | |
| } | |
| } catch { | |
| message = zodData; | |
| } | |
| } | |
| } | |
| } else if (error instanceof Error) { | |
| message = error.message; | |
| // Check for network fetch failures | |
| if ( | |
| message.includes("Failed to fetch") || | |
| message.includes("NetworkError") || | |
| message.includes("Load failed") | |
| ) { | |
| isNetworkError = true; | |
| title = "Connection Lost"; | |
| message = "Unable to connect to the server. Please verify your internet connection."; | |
| } | |
| } else if (typeof error === "string") { | |
| message = error; | |
| } else if (typeof error === "object" && error !== null) { | |
| const errObj = error as Record<string, any>; | |
| if (errObj.message) message = String(errObj.message); | |
| if (errObj.code) code = String(errObj.code); | |
| if (errObj.statusCode) statusCode = Number(errObj.statusCode); | |
| if (errObj.requestId) requestId = String(errObj.requestId); | |
| } | |
| // Status code / Code specific titling & messages | |
| const isRateLimit = statusCode === 429 || code === "TOO_MANY_REQUESTS" || message.toLowerCase().includes("rate limit"); | |
| const isAuthError = statusCode === 401 || code === "UNAUTHORIZED"; | |
| const isForbidden = statusCode === 403 || code === "FORBIDDEN"; | |
| const isNotFound = statusCode === 404 || code === "NOT_FOUND"; | |
| if (isRateLimit) { | |
| title = "Rate Limit Reached"; | |
| message = "You have made too many requests. Please pause for a few seconds before trying again."; | |
| } else if (isAuthError) { | |
| title = "Authentication Required"; | |
| message = "Your session has expired or you are not logged in. Please sign in to continue."; | |
| } else if (isForbidden) { | |
| title = "Access Denied"; | |
| message = "You do not have permission to perform this action. You may need to upgrade your subscription plan or ask a workspace admin."; | |
| } else if (isNotFound) { | |
| title = "Resource Not Found"; | |
| } | |
| return { | |
| title, | |
| message, | |
| statusCode, | |
| code, | |
| requestId, | |
| fieldErrors, | |
| isNetworkError, | |
| isRateLimit, | |
| isAuthError, | |
| isForbidden, | |
| isNotFound, | |
| }; | |
| } | |
| export function formatErrorMessage(error: unknown, fallbackMessage?: string): string { | |
| return parseError(error, fallbackMessage).message; | |
| } | |