diff --git a/frontend/src/app/global-error.tsx b/frontend/src/app/global-error.tsx index 9532023d39..b1550b16b3 100644 --- a/frontend/src/app/global-error.tsx +++ b/frontend/src/app/global-error.tsx @@ -62,7 +62,11 @@ export class AppError extends Error { } } -export const handleAppError = (error: unknown) => { +interface HandleAppErrorOptions { + timeout?: number +} + +export const handleAppError = (error: unknown, options?: HandleAppErrorOptions) => { let appError: AppError if (error instanceof AppError) { @@ -81,7 +85,7 @@ export const handleAppError = (error: unknown) => { addToast({ title: errorConfig.title, description: appError.message || errorConfig.message, - timeout: 5000, + timeout: options?.timeout ?? 5000, variant: 'solid', color: 'danger', shouldShowTimeoutProgress: true, diff --git a/frontend/src/utils/helpers/apolloClient.ts b/frontend/src/utils/helpers/apolloClient.ts index 42fdbeca87..d203e29882 100644 --- a/frontend/src/utils/helpers/apolloClient.ts +++ b/frontend/src/utils/helpers/apolloClient.ts @@ -3,15 +3,44 @@ import { setContext } from '@apollo/client/link/context' import { AppError, handleAppError } from 'app/global-error' import { GRAPHQL_URL } from 'utils/env.client' import { getCsrfToken } from 'utils/utility' + +let hasShownGraphQLConnectionError = false + +const notifyGraphQLConnectionError = () => { + if (hasShownGraphQLConnectionError) { + return + } + + hasShownGraphQLConnectionError = true + handleAppError( + new AppError( + 500, + 'Unable to reach the GraphQL backend. Ensure the backend service is running and NEXT_PUBLIC_GRAPHQL_URL points to a valid /graphql/ endpoint.' + ), + { timeout: 12000 } + ) +} + const createApolloClient = () => { if (!GRAPHQL_URL) { - const error = new AppError(500, 'Missing GraphQL URL') + const error = new AppError( + 500, + 'Missing NEXT_PUBLIC_GRAPHQL_URL. Set it in frontend/.env and ensure the backend GraphQL service is running.' + ) handleAppError(error) return null } const httpLink = new HttpLink({ credentials: 'include', + fetch: async (uri, options) => { + try { + return await fetch(uri, options) + } catch (error) { + notifyGraphQLConnectionError() + throw error + } + }, uri: GRAPHQL_URL, }) diff --git a/frontend/src/wrappers/provider.tsx b/frontend/src/wrappers/provider.tsx index 974bdb304d..6de64f3afa 100644 --- a/frontend/src/wrappers/provider.tsx +++ b/frontend/src/wrappers/provider.tsx @@ -24,8 +24,17 @@ export function Providers({ }>) { if (!apolloClient) { return ( -
+ The frontend could not initialize Apollo because the GraphQL endpoint is unavailable. +
++ Set NEXT_PUBLIC_GRAPHQL_URL in frontend/.env and ensure the backend GraphQL service + is running. +
+