diff --git a/.changeset/error_page_with_report.md b/.changeset/error_page_with_report.md
new file mode 100644
index 000000000..3a619c8d1
--- /dev/null
+++ b/.changeset/error_page_with_report.md
@@ -0,0 +1,5 @@
+---
+sable: minor
+---
+
+added error page making it easier to report errors when they occur in the field
diff --git a/src/app/components/DefaultErrorPage.tsx b/src/app/components/DefaultErrorPage.tsx
new file mode 100644
index 000000000..edf8acf5f
--- /dev/null
+++ b/src/app/components/DefaultErrorPage.tsx
@@ -0,0 +1,116 @@
+import { Box, Button, Dialog, Icon, Icons, Text, color, config } from 'folds';
+import { SplashScreen } from '$components/splash-screen';
+import { buildGitHubUrl } from '$features/bug-report/BugReportModal';
+
+type ErrorPageProps = {
+ error: Error;
+};
+
+function createIssueUrl(error: Error): string {
+ const stacktrace = error.stack || 'No stacktrace available';
+
+ const automatedBugReport = `# Automated Bug Report
+Error occurred in the application.
+
+## Error Message
+\`\`\`
+${error.message}
+\`\`\`
+
+## Stacktrace
+\`\`\`
+${stacktrace}
+\`\`\``;
+
+ return buildGitHubUrl('bug', `Error: ${error.message}`, { context: automatedBugReport });
+}
+
+// This component is used as the fallback for the ErrorBoundary in App.tsx, which means it will be rendered whenever an uncaught error is thrown in any of the child components and not handled locally.
+// It provides a user-friendly error message and options to report the issue or reload the page.
+// Motivation of the design is to encourage users to report issues while also providing them with the necessary information to do so, and to give them an easy way to recover by reloading the page.
+// Note: Since this component is rendered in response to an error, it should be as resilient as possible and avoid any complex logic or dependencies that could potentially throw additional errors.
+export function ErrorPage({ error }: ErrorPageProps) {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/src/app/features/bug-report/BugReportModal.tsx b/src/app/features/bug-report/BugReportModal.tsx
index 1ee788f05..2f90fda31 100644
--- a/src/app/features/bug-report/BugReportModal.tsx
+++ b/src/app/features/bug-report/BugReportModal.tsx
@@ -52,7 +52,11 @@ async function searchSimilarIssues(query: string, signal: AbortSignal): Promise<
// Field IDs match the ids defined in .github/ISSUE_TEMPLATE/bug_report.yml
// and feature_request.yml so GitHub pre-fills each form field directly.
-function buildGitHubUrl(type: ReportType, title: string, fields: Record): string {
+export function buildGitHubUrl(
+ type: ReportType,
+ title: string,
+ fields: Record
+): string {
const devLabel = IS_RELEASE_TAG ? '' : '-dev';
const buildLabel = BUILD_HASH ? ` (${BUILD_HASH})` : '';
const version = `v${APP_VERSION}${devLabel}${buildLabel}`;
diff --git a/src/app/pages/App.tsx b/src/app/pages/App.tsx
index bfe51f2a9..0408f38ea 100644
--- a/src/app/pages/App.tsx
+++ b/src/app/pages/App.tsx
@@ -3,11 +3,13 @@ import { OverlayContainerProvider, PopOutContainerProvider, TooltipContainerProv
import { RouterProvider } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
+import { ErrorBoundary } from 'react-error-boundary';
import { ClientConfigLoader } from '$components/ClientConfigLoader';
import { ClientConfigProvider } from '$hooks/useClientConfig';
import { ScreenSizeProvider, useScreenSize } from '$hooks/useScreenSize';
import { useCompositionEndTracking } from '$hooks/useComposingCheck';
+import { ErrorPage } from '$components/DefaultErrorPage';
import { ConfigConfigError, ConfigConfigLoading } from './ConfigConfig';
import { FeatureCheck } from './FeatureCheck';
import { createRouter } from './Router';
@@ -21,33 +23,35 @@ function App() {
const portalContainer = document.getElementById('portalContainer') ?? undefined;
return (
-
-
-
-
-
- }
- error={(err, retry, ignore) => (
-
- )}
- >
- {(clientConfig) => (
-
-
-
-
-
-
-
-
- )}
-
-
-
-
-
-
+
+
+
+
+
+
+ }
+ error={(err, retry, ignore) => (
+
+ )}
+ >
+ {(clientConfig) => (
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+
+
+
);
}