diff --git a/packages/server/src/utils/quotaUsage.ts b/packages/server/src/utils/quotaUsage.ts
index e2cf382d4dc..35cf855aa1b 100644
--- a/packages/server/src/utils/quotaUsage.ts
+++ b/packages/server/src/utils/quotaUsage.ts
@@ -70,7 +70,7 @@ export const checkUsageLimit = async (
if (limit === -1) return
if (currentUsage > limit) {
- throw new InternalFlowiseError(StatusCodes.TOO_MANY_REQUESTS, `Limit exceeded: ${type}`)
+ throw new InternalFlowiseError(StatusCodes.PAYMENT_REQUIRED, `Limit exceeded: ${type}`)
}
}
@@ -135,7 +135,7 @@ export const checkPredictions = async (orgId: string, subscriptionId: string, us
if (predictionsLimit === -1) return
if (currentPredictions >= predictionsLimit) {
- throw new InternalFlowiseError(StatusCodes.TOO_MANY_REQUESTS, 'Predictions limit exceeded')
+ throw new InternalFlowiseError(StatusCodes.PAYMENT_REQUIRED, 'Predictions limit exceeded')
}
return {
@@ -161,7 +161,7 @@ export const checkStorage = async (orgId: string, subscriptionId: string, usageC
if (storageLimit === -1) return
if (currentStorageUsage >= storageLimit) {
- throw new InternalFlowiseError(StatusCodes.TOO_MANY_REQUESTS, 'Storage limit exceeded')
+ throw new InternalFlowiseError(StatusCodes.PAYMENT_REQUIRED, 'Storage limit exceeded')
}
return {
diff --git a/packages/ui/src/routes/AuthRoutes.jsx b/packages/ui/src/routes/AuthRoutes.jsx
index 2d63fc38719..eb303b98c13 100644
--- a/packages/ui/src/routes/AuthRoutes.jsx
+++ b/packages/ui/src/routes/AuthRoutes.jsx
@@ -10,6 +10,7 @@ const VerifyEmailPage = Loadable(lazy(() => import('@/views/auth/verify-email'))
const ForgotPasswordPage = Loadable(lazy(() => import('@/views/auth/forgotPassword')))
const ResetPasswordPage = Loadable(lazy(() => import('@/views/auth/resetPassword')))
const UnauthorizedPage = Loadable(lazy(() => import('@/views/auth/unauthorized')))
+const RateLimitedPage = Loadable(lazy(() => import('@/views/auth/rateLimited')))
const OrganizationSetupPage = Loadable(lazy(() => import('@/views/organization/index')))
const LicenseExpiredPage = Loadable(lazy(() => import('@/views/auth/expired')))
@@ -45,6 +46,10 @@ const AuthRoutes = {
path: '/unauthorized',
element:
},
+ {
+ path: '/rate-limited',
+ element:
+ },
{
path: '/organization-setup',
element:
diff --git a/packages/ui/src/store/context/ErrorContext.jsx b/packages/ui/src/store/context/ErrorContext.jsx
index e41070a1516..9201242acf4 100644
--- a/packages/ui/src/store/context/ErrorContext.jsx
+++ b/packages/ui/src/store/context/ErrorContext.jsx
@@ -14,7 +14,22 @@ export const ErrorProvider = ({ children }) => {
const handleError = async (err) => {
console.error(err)
- if (err?.response?.status === 403) {
+ if (err?.response?.status === 429) {
+ const retryAfterHeader = err?.response?.headers?.['retry-after']
+ let retryAfter = 60 // Default in seconds
+ if (retryAfterHeader) {
+ const parsedSeconds = parseInt(retryAfterHeader, 10)
+ if (Number.isNaN(parsedSeconds)) {
+ const retryDate = new Date(retryAfterHeader)
+ if (!Number.isNaN(retryDate.getTime())) {
+ retryAfter = Math.max(0, Math.ceil((retryDate.getTime() - Date.now()) / 1000))
+ }
+ } else {
+ retryAfter = parsedSeconds
+ }
+ }
+ navigate('/rate-limited', { state: { retryAfter } })
+ } else if (err?.response?.status === 403) {
navigate('/unauthorized')
} else if (err?.response?.status === 401) {
if (ErrorMessage.INVALID_MISSING_TOKEN === err?.response?.data?.message) {
diff --git a/packages/ui/src/views/auth/rateLimited.jsx b/packages/ui/src/views/auth/rateLimited.jsx
new file mode 100644
index 00000000000..44b8a85dd6f
--- /dev/null
+++ b/packages/ui/src/views/auth/rateLimited.jsx
@@ -0,0 +1,51 @@
+import { Box, Button, Stack, Typography } from '@mui/material'
+import { Link, useLocation } from 'react-router-dom'
+import unauthorizedSVG from '@/assets/images/unauthorized.svg'
+import MainCard from '@/ui-component/cards/MainCard'
+
+// ==============================|| RateLimitedPage ||============================== //
+
+const RateLimitedPage = () => {
+ const location = useLocation()
+
+ const retryAfter = location.state?.retryAfter || 60
+
+ return (
+
+
+
+
+
+
+
+ 429 Too Many Requests
+
+
+ {`You have made too many requests in a short period of time. Please wait ${retryAfter}s before trying again.`}
+
+
+
+
+
+
+
+ )
+}
+
+export default RateLimitedPage