diff --git a/libs/shared/lib/components/errorBoundary/ErrorBoundary.tsx b/libs/shared/lib/components/errorBoundary/ErrorBoundary.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..14908635c37f4ed4522542e57c74b22eff82992b
--- /dev/null
+++ b/libs/shared/lib/components/errorBoundary/ErrorBoundary.tsx
@@ -0,0 +1,48 @@
+import React, { Component, ErrorInfo, ReactNode } from 'react';
+import { Button } from '../buttons';
+
+interface ErrorBoundaryProps {
+  children: ReactNode;
+  fallback?: ReactNode;
+  onError?: (error: Error, errorInfo: ErrorInfo) => void;
+}
+
+interface ErrorBoundaryState {
+  hasError: boolean;
+}
+
+class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
+  constructor(props: ErrorBoundaryProps) {
+    super(props);
+    this.state = { hasError: false };
+  }
+
+  static getDerivedStateFromError(): ErrorBoundaryState {
+    return { hasError: true };
+  }
+
+  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
+    if (this.props.onError) {
+      this.props.onError(error, errorInfo);
+    }
+  }
+
+  handleRetry() {
+    this.setState({ hasError: false });
+  }
+
+  render() {
+    if (this.state.hasError) {
+      return (
+        <div>
+          {this.props.fallback || <div>Something went wrong. Please try again later.</div>}
+          <Button label="Retry now" variant="outline" variantType="primary" onClick={this.handleRetry} />
+        </div>
+      );
+    }
+
+    return this.props.children;
+  }
+}
+
+export { ErrorBoundary };
diff --git a/libs/shared/lib/components/errorBoundary/index.ts b/libs/shared/lib/components/errorBoundary/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..43a371efcb52aa53fa73cf07a189a098fa4c1143
--- /dev/null
+++ b/libs/shared/lib/components/errorBoundary/index.ts
@@ -0,0 +1 @@
+export * from './ErrorBoundary';
diff --git a/libs/shared/lib/vis/components/VisualizationPanel.tsx b/libs/shared/lib/vis/components/VisualizationPanel.tsx
index 1b6eba6ea99846b060ee2fb974b2360c45fa1008..b39ab2f80b3f0f0e7fb2a4da996ba180263c9672 100644
--- a/libs/shared/lib/vis/components/VisualizationPanel.tsx
+++ b/libs/shared/lib/vis/components/VisualizationPanel.tsx
@@ -15,6 +15,8 @@ import { Recommender, NoData, Querying } from '../views';
 import { resultSetFocus, resultSetSelection, unSelect } from '../../data-access/store/interactionSlice';
 import { updateVisualization, addVisualization } from '../../data-access/store/visualizationSlice';
 import { VisualizationPropTypes, VISComponentType } from '../common';
+import { ErrorBoundary } from '../../components/errorBoundary';
+import { addError } from '../../data-access/store/configSlice';
 
 type PromiseFunc = () => Promise<{ default: VISComponentType<any> }>;
 export const Visualizations: Record<string, PromiseFunc> = {
@@ -83,6 +85,7 @@ export const VisualizationPanel = ({ fullSize }: { fullSize: () => void }) => {
     }
   };
   const exportImage = viz?.exportImage || (() => {});
+
   return (
     <div
       className="relative pt-7 vis-panel h-full w-full flex flex-col border bg-light"
@@ -98,23 +101,31 @@ export const VisualizationPanel = ({ fullSize }: { fullSize: () => void }) => {
         ) : (
           <div className="w-full h-full flex">
             <Suspense fallback={<div>Loading...</div>}>
-              {!!viz &&
-                activeVisualizationIndex !== -1 &&
-                openVisualizationArray?.[activeVisualizationIndex] &&
-                viz.id === openVisualizationArray[activeVisualizationIndex].id &&
-                graphMetadata && (
-                  <viz.component
-                    data={graphQueryResult}
-                    schema={schema}
-                    ml={ml}
-                    settings={openVisualizationArray[activeVisualizationIndex]}
-                    dispatch={dispatch}
-                    handleSelect={handleSelect}
-                    graphMetadata={graphMetadata}
-                    updateSettings={updateSettings}
-                    handleHover={() => {}}
-                  />
-                )}
+              <ErrorBoundary
+                fallback={<div>Something went wrong</div>}
+                onError={() => {
+                  dispatch(addError('Something went wrong while trying to load the visualization'));
+                  setViz(undefined);
+                }}
+              >
+                {!!viz &&
+                  activeVisualizationIndex !== -1 &&
+                  openVisualizationArray?.[activeVisualizationIndex] &&
+                  viz.id === openVisualizationArray[activeVisualizationIndex].id &&
+                  graphMetadata && (
+                    <viz.component
+                      data={graphQueryResult}
+                      schema={schema}
+                      ml={ml}
+                      settings={openVisualizationArray[activeVisualizationIndex]}
+                      dispatch={dispatch}
+                      handleSelect={handleSelect}
+                      graphMetadata={graphMetadata}
+                      updateSettings={updateSettings}
+                      handleHover={() => {}}
+                    />
+                  )}
+              </ErrorBoundary>
             </Suspense>
           </div>
         )}