diff --git a/package-lock.json b/package-lock.json
index a1966db0917e65b4f510518c19e2655f98633fc9..18eaa14c5846910e2f3e54e7f06fffe2987b4f93 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -35,6 +35,7 @@
         "react-dom": "18.2.0",
         "react-dropzone": "^14.2.3",
         "react-redux": "^8.1.2",
+        "sonner": "^1.4.3",
         "tailwind-merge": "^1.14.0",
         "tailwindcss": "3.3.3",
         "ts-deepmerge": "^6.2.0",
@@ -12410,6 +12411,15 @@
         "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
+    "node_modules/sonner": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.4.3.tgz",
+      "integrity": "sha512-SArYlHbkjqRuLiR0iGY2ZSr09oOrxw081ZZkQPfXrs8aZQLIBOLOdzTYxGJB5yIZ7qL56UEPmrX1YqbODwG0Lw==",
+      "peerDependencies": {
+        "react": "^18.0.0",
+        "react-dom": "^18.0.0"
+      }
+    },
     "node_modules/source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -22963,6 +22973,12 @@
         }
       }
     },
+    "sonner": {
+      "version": "1.4.3",
+      "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.4.3.tgz",
+      "integrity": "sha512-SArYlHbkjqRuLiR0iGY2ZSr09oOrxw081ZZkQPfXrs8aZQLIBOLOdzTYxGJB5yIZ7qL56UEPmrX1YqbODwG0Lw==",
+      "requires": {}
+    },
     "source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
diff --git a/package.json b/package.json
index f44f22efed3236434a8bad77d7b52e0245284733..54dfdef6f81b5365f64141c7b74a92f419bdae94 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,7 @@
     "react-dom": "18.2.0",
     "react-dropzone": "^14.2.3",
     "react-redux": "^8.1.2",
+    "sonner": "^1.4.3",
     "tailwind-merge": "^1.14.0",
     "tailwindcss": "3.3.3",
     "ts-deepmerge": "^6.2.0",
diff --git a/src/components/AppWrapper/AppWrapper.component.tsx b/src/components/AppWrapper/AppWrapper.component.tsx
index 3b59e82bec77dc93528d14168014000abd095242..5014ee69cbf7e8d0baed57003a58d81dfe049335 100644
--- a/src/components/AppWrapper/AppWrapper.component.tsx
+++ b/src/components/AppWrapper/AppWrapper.component.tsx
@@ -2,6 +2,7 @@ import { store } from '@/redux/store';
 import { MapInstanceProvider } from '@/utils/context/mapInstanceContext';
 import { ReactNode } from 'react';
 import { Provider } from 'react-redux';
+import { Toaster } from 'sonner';
 
 interface AppWrapperProps {
   children: ReactNode;
@@ -9,6 +10,17 @@ interface AppWrapperProps {
 
 export const AppWrapper = ({ children }: AppWrapperProps): JSX.Element => (
   <MapInstanceProvider>
-    <Provider store={store}>{children}</Provider>
+    <Provider store={store}>
+      <>
+        <Toaster
+          position="top-center"
+          visibleToasts={1}
+          style={{
+            width: '700px',
+          }}
+        />
+        {children}
+      </>
+    </Provider>
   </MapInstanceProvider>
 );
diff --git a/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx b/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
index f0934d79f6f54d7ea9008e43f5e84ba7f5faac04..990e4fbdb080ffe640223359edc15521dcfb5053 100644
--- a/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
@@ -11,10 +11,13 @@ import { HttpStatusCode } from 'axios';
 import { DEFAULT_ERROR } from '@/constants/errors';
 import { act } from 'react-dom/test-utils';
 import { OVERLAYS_INITIAL_STATE_MOCK } from '@/redux/overlays/overlays.mock';
+import { showToast } from '@/utils/showToast';
 import { Modal } from '../Modal.component';
 
 const mockedAxiosClient = mockNetworkResponse();
 
+jest.mock('../../../../utils/showToast');
+
 const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
   const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
 
@@ -31,6 +34,9 @@ const renderComponent = (initialStoreState: InitialStoreState = {}): { store: St
 };
 
 describe('EditOverlayModal - component', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
   it('should render modal with correct data', () => {
     renderComponent({
       modal: {
@@ -101,6 +107,39 @@ describe('EditOverlayModal - component', () => {
     expect(loading).toBe('succeeded');
     expect(removeButton).not.toBeVisible();
   });
+  it('should show toast after successful removing user overlay', async () => {
+    renderComponent({
+      user: {
+        authenticated: true,
+        loading: 'succeeded',
+        error: DEFAULT_ERROR,
+        login: 'test',
+      },
+      modal: {
+        isOpen: true,
+        modalTitle: overlayFixture.name,
+        modalName: 'edit-overlay',
+        editOverlayState: overlayFixture,
+        molArtState: {},
+        overviewImagesState: {},
+      },
+      overlays: OVERLAYS_INITIAL_STATE_MOCK,
+    });
+    mockedAxiosClient
+      .onDelete(apiPath.removeOverlay(overlayFixture.idObject))
+      .reply(HttpStatusCode.Ok, {});
+
+    const removeButton = screen.getByTestId('remove-button');
+    expect(removeButton).toBeVisible();
+    await act(() => {
+      removeButton.click();
+    });
+
+    expect(showToast).toHaveBeenCalledWith({
+      message: 'User overlay removed successfully',
+      type: 'success',
+    });
+  });
   it('should handle save edited user overlay', async () => {
     const { store } = renderComponent({
       user: {
@@ -133,6 +172,39 @@ describe('EditOverlayModal - component', () => {
     expect(loading).toBe('succeeded');
     expect(saveButton).not.toBeVisible();
   });
+  it('should show toast after successful editing user overlay', async () => {
+    renderComponent({
+      user: {
+        authenticated: true,
+        loading: 'succeeded',
+        error: DEFAULT_ERROR,
+        login: 'test',
+      },
+      modal: {
+        isOpen: true,
+        modalTitle: overlayFixture.name,
+        modalName: 'edit-overlay',
+        editOverlayState: overlayFixture,
+        molArtState: {},
+        overviewImagesState: {},
+      },
+      overlays: OVERLAYS_INITIAL_STATE_MOCK,
+    });
+    mockedAxiosClient
+      .onPatch(apiPath.updateOverlay(overlayFixture.idObject))
+      .reply(HttpStatusCode.Ok, overlayFixture);
+
+    const saveButton = screen.getByTestId('save-button');
+    expect(saveButton).toBeVisible();
+    await act(() => {
+      saveButton.click();
+    });
+
+    expect(showToast).toHaveBeenCalledWith({
+      message: 'User overlay updated successfully',
+      type: 'success',
+    });
+  });
 
   it('should handle cancel edit user overlay', async () => {
     const { store } = renderComponent({
diff --git a/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.ts b/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.ts
index 63a98d5e96cacc5fb1d6c5f34f0a5ba94a5f2ec2..a8d02776d6eb4320f841e7dbea919cffb3134a37 100644
--- a/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.ts
+++ b/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.ts
@@ -76,10 +76,10 @@ export const useEditOverlay = (): UseEditOverlayReturn => {
   };
 
   const handleSaveEditedOverlay = async (): Promise<void> => {
-    if (!currentEditedOverlay || !name || !description || !login) return;
+    if (!currentEditedOverlay || !name || !login) return;
     await handleUpdateOverlay({
       editedOverlay: currentEditedOverlay,
-      overlayDescription: description,
+      overlayDescription: description || '',
       overlayName: name,
     });
 
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/AvailablePluginsDrawer.constants.ts b/src/components/Map/Drawer/AvailablePluginsDrawer/AvailablePluginsDrawer.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e628e141901704881c7243aea0324512518107ad
--- /dev/null
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/AvailablePluginsDrawer.constants.ts
@@ -0,0 +1 @@
+export const PLUGIN_LOADING_ERROR_PREFIX = 'Failed to load plugin';
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.test.ts b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.test.ts
index 0ea19da098cf1edb70be6367ba25b12d06b7e992..f54c8f5bd2c0bf9ce531f8482d7c0cee13928338 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.test.ts
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.test.ts
@@ -7,10 +7,12 @@ import { renderHook, waitFor } from '@testing-library/react';
 import axios, { HttpStatusCode } from 'axios';
 import MockAdapter from 'axios-mock-adapter';
 import { act } from 'react-dom/test-utils';
+import { showToast } from '@/utils/showToast';
 import { useLoadPlugin } from './useLoadPlugin';
 
 const mockedAxiosClient = new MockAdapter(axios);
 jest.mock('../../../../../../services/pluginsManager/pluginsManager');
+jest.mock('../../../../../../utils/showToast');
 
 describe('useLoadPlugin', () => {
   afterEach(() => {
@@ -86,4 +88,31 @@ describe('useLoadPlugin', () => {
       });
     });
   });
+  it('should show toast if plugin failed to load', async () => {
+    const hash = 'pluginHash';
+    const pluginUrl = 'http://example.com/plugin.js';
+
+    const { Wrapper } = getReduxStoreWithActionsListener(INITIAL_STORE_STATE_MOCK);
+
+    mockedAxiosClient.onGet(pluginUrl).reply(HttpStatusCode.Forbidden, null);
+
+    const {
+      result: {
+        current: { togglePlugin },
+      },
+    } = renderHook(() => useLoadPlugin({ hash, pluginUrl }), {
+      wrapper: Wrapper,
+    });
+
+    togglePlugin();
+
+    await waitFor(() => {
+      expect(showToast).toHaveBeenCalled();
+      expect(showToast).toHaveBeenCalledWith({
+        message:
+          "Failed to load plugin: Access Forbidden! You don't have permission to access this resource.",
+        type: 'error',
+      });
+    });
+  });
 });
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.ts b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.ts
index 454347303ae79a4683debd742c0108152eef805b..ebce11ec92f224772b10aa40c48e33b1cc9051b7 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.ts
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.ts
@@ -7,7 +7,10 @@ import {
 } from '@/redux/plugins/plugins.selectors';
 import { removePlugin } from '@/redux/plugins/plugins.slice';
 import { PluginsManager } from '@/services/pluginsManager';
+import { showToast } from '@/utils/showToast';
 import axios from 'axios';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { PLUGIN_LOADING_ERROR_PREFIX } from '../../AvailablePluginsDrawer.constants';
 
 type UseLoadPluginReturnType = {
   togglePlugin: () => void;
@@ -37,21 +40,29 @@ export const useLoadPlugin = ({
   const dispatch = useAppDispatch();
 
   const handleLoadPlugin = async (): Promise<void> => {
-    const response = await axios(pluginUrl);
-    const pluginScript = response.data;
+    try {
+      const response = await axios(pluginUrl);
+      const pluginScript = response.data;
 
-    /* eslint-disable no-new-func */
-    const loadPlugin = new Function(pluginScript);
+      /* eslint-disable no-new-func */
+      const loadPlugin = new Function(pluginScript);
 
-    PluginsManager.setHashedPlugin({
-      pluginUrl,
-      pluginScript,
-    });
+      PluginsManager.setHashedPlugin({
+        pluginUrl,
+        pluginScript,
+      });
 
-    loadPlugin();
+      loadPlugin();
 
-    if (onPluginLoaded) {
-      onPluginLoaded();
+      if (onPluginLoaded) {
+        onPluginLoaded();
+      }
+    } catch (error) {
+      const errorMessage = getErrorMessage({
+        error,
+        prefix: PLUGIN_LOADING_ERROR_PREFIX,
+      });
+      showToast({ type: 'error', message: errorMessage });
     }
   };
 
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx
index e6a8094dfe823a13d6ca8dd966b23b5f2e702d5e..1b347d6eec569ab743acd711450aa4479f0cb808 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx
@@ -13,11 +13,14 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
 import axios, { HttpStatusCode } from 'axios';
 import MockAdapter from 'axios-mock-adapter';
 import { act } from 'react-dom/test-utils';
+import { showToast } from '@/utils/showToast';
 import { LoadPluginFromUrl } from './LoadPluginFromUrl.component';
 
 const mockedAxiosApiClient = mockNetworkResponse();
 const mockedAxiosClient = new MockAdapter(axios);
 
+jest.mock('../../../../../utils/showToast');
+
 const renderComponent = (initialStore?: InitialStoreState): { store: StoreType } => {
   const { Wrapper, store } = getReduxWrapperWithStore(initialStore);
   return (
@@ -163,6 +166,35 @@ describe('LoadPluginFromUrl - component', () => {
       const button = screen.getByTestId('load-plugin-button');
       expect(button).toBeDisabled();
     });
+    it('should show toast if plugin failed to load', async () => {
+      const pluginUrl = 'http://example.com/plugin.js';
+      mockedAxiosClient.onGet(pluginUrl).reply(HttpStatusCode.Unauthorized, null);
+
+      global.URL.canParse = jest.fn().mockReturnValue(true);
+
+      renderComponent();
+      const input = screen.getByTestId('load-plugin-input-url');
+      expect(input).toBeVisible();
+
+      act(() => {
+        fireEvent.change(input, { target: { value: pluginUrl } });
+      });
+
+      const button = screen.getByTestId('load-plugin-button');
+
+      act(() => {
+        button.click();
+      });
+
+      await waitFor(() => {
+        expect(showToast).toHaveBeenCalled();
+        expect(showToast).toHaveBeenCalledWith({
+          message:
+            "Failed to load plugin: You're not authorized to access this resource. Please log in or check your credentials.",
+          type: 'error',
+        });
+      });
+    });
     it('should set plugin active tab in drawer as loaded plugin', async () => {
       const pluginUrl = 'http://example.com/plugin.js';
       const pluginScript = `function init() {} init()`;
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
index 93d0f0148b9d27018ca289e1cfffcbbb11d7e847..f95bdf7e4beaa78a655090c648652a8ff20fa388 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
@@ -3,8 +3,11 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { activePluginsDataSelector } from '@/redux/plugins/plugins.selectors';
 import { setCurrentDrawerPluginHash } from '@/redux/plugins/plugins.slice';
 import { PluginsManager } from '@/services/pluginsManager';
+import { showToast } from '@/utils/showToast';
 import axios from 'axios';
 import { ChangeEvent, useMemo, useState } from 'react';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { PLUGIN_LOADING_ERROR_PREFIX } from '../../AvailablePluginsDrawer.constants';
 
 type UseLoadPluginReturnType = {
   handleChangePluginUrl: (event: ChangeEvent<HTMLInputElement>) => void;
@@ -49,6 +52,12 @@ export const useLoadPluginFromUrl = (): UseLoadPluginReturnType => {
       setPluginUrl('');
 
       handleSetCurrentDrawerPluginHash(hash);
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: PLUGIN_LOADING_ERROR_PREFIX });
+      showToast({
+        type: 'error',
+        message: errorMessage,
+      });
     } finally {
       setIsLoading(false);
     }
diff --git a/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx b/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx
index 474934d8f7bf9805432330ca0361a9ee2a7572e3..b9966147dd4a91994d39bf8b39a03f66f9e6224c 100644
--- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx
+++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx
@@ -21,8 +21,11 @@ import {
 } from '@/models/fixtures/overlaysFixture';
 import { OVERLAYS_INITIAL_STATE_MOCK } from '@/redux/overlays/overlays.mock';
 import { DEFAULT_ERROR } from '@/constants/errors';
+import { showToast } from '@/utils/showToast';
 import { UserOverlayForm } from './UserOverlayForm.component';
 
+jest.mock('../../../../../utils/showToast');
+
 const mockedAxiosClient = mockNetworkResponse();
 
 const renderComponent = (initialStore?: InitialStoreState): { store: StoreType } => {
@@ -57,6 +60,9 @@ const renderComponentWithActionListener = (
 };
 
 describe('UserOverlayForm - Component', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
   it('renders the UserOverlayForm component', () => {
     renderComponent();
 
@@ -249,4 +255,58 @@ describe('UserOverlayForm - Component', () => {
       expect(refetchedUserOverlays).toEqual(overlaysFixture);
     });
   });
+  it('should show toast after successful creating user overlays', async () => {
+    mockedAxiosClient
+      .onPost(apiPath.createOverlayFile())
+      .reply(HttpStatusCode.Ok, createdOverlayFileFixture);
+
+    mockedAxiosClient
+      .onPost(apiPath.uploadOverlayFileContent(createdOverlayFileFixture.id))
+      .reply(HttpStatusCode.Ok, uploadedOverlayFileContentFixture);
+
+    mockedAxiosClient
+      .onPost(apiPath.createOverlay(projectFixture.projectId))
+      .reply(HttpStatusCode.Ok, createdOverlayFixture);
+
+    mockedAxiosClient
+      .onGet(apiPath.getAllUserOverlaysByCreatorQuery({ creator: 'test', publicOverlay: false }))
+      .reply(HttpStatusCode.Ok, overlaysFixture);
+
+    const { store } = renderComponent({
+      user: {
+        authenticated: true,
+        error: DEFAULT_ERROR,
+        login: 'test',
+        loading: 'succeeded',
+      },
+      project: {
+        data: projectFixture,
+        loading: 'succeeded',
+        error: DEFAULT_ERROR,
+      },
+      overlays: OVERLAYS_INITIAL_STATE_MOCK,
+    });
+
+    const userOverlays = store.getState().overlays.userOverlays.data;
+
+    expect(userOverlays).toEqual([]);
+
+    fireEvent.change(screen.getByTestId('overlay-name'), { target: { value: 'Test Overlay' } });
+    fireEvent.change(screen.getByTestId('overlay-description'), {
+      target: { value: 'Description Overlay' },
+    });
+    fireEvent.change(screen.getByTestId('overlay-elements-list'), {
+      target: { value: 'Elements List Overlay' },
+    });
+
+    fireEvent.click(screen.getByLabelText('upload overlay'));
+
+    await waitFor(() => {
+      expect(showToast).toHaveBeenCalled();
+      expect(showToast).toHaveBeenCalledWith({
+        message: 'User overlay added successfully',
+        type: 'success',
+      });
+    });
+  });
 });
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts
index 40874a2d452162994079b8fe60b7be1fbf56959b..bab0bd6227775d92db2c5edfc8f15c1d9377aa6b 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleAliasResults.ts
@@ -29,7 +29,5 @@ export const handleAliasResults =
           if (hasFitBounds) {
             searchFitBounds(fitBoundsZoom);
           }
-        }).catch(() => {
-          // TODO to discuss manage state of failure
         });
     };
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts
index 24332182531f770a76a2372c29e6586a89cf2e33..bcadc4a1e476956a6c62d7a190f502924294251b 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.ts
@@ -41,7 +41,5 @@ export const handleReactionResults =
         if (hasFitBounds) {
           searchFitBounds(fitBoundsZoom);
         }
-      }).catch(() => {
-        // TODO to discuss manage state of failure
       });
     };
diff --git a/src/redux/backgrounds/backgrounds.constants.ts b/src/redux/backgrounds/backgrounds.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0fa103f27a2b1c77b8521798570f223a6ac4f6d0
--- /dev/null
+++ b/src/redux/backgrounds/backgrounds.constants.ts
@@ -0,0 +1 @@
+export const BACKGROUNDS_FETCHING_ERROR_PREFIX = 'Failed to fetch backgrounds';
diff --git a/src/redux/backgrounds/backgrounds.reducers.test.ts b/src/redux/backgrounds/backgrounds.reducers.test.ts
index 9b99161ae9290ee475248566ffe020cc56dc0561..4f70938fa505c0da1813ec8df6cf16e2f9fe4ad8 100644
--- a/src/redux/backgrounds/backgrounds.reducers.test.ts
+++ b/src/redux/backgrounds/backgrounds.reducers.test.ts
@@ -11,6 +11,8 @@ import backgroundsReducer from './backgrounds.slice';
 import { getAllBackgroundsByProjectId } from './backgrounds.thunks';
 import { BackgroundsState } from './backgrounds.types';
 
+jest.mock('../../utils/showToast');
+
 const mockedAxiosClient = mockNetworkResponse();
 
 const INITIAL_STATE: BackgroundsState = {
@@ -49,13 +51,16 @@ describe('backgrounds reducer', () => {
       .onGet(apiPath.getAllBackgroundsByProjectIdQuery(PROJECT_ID))
       .reply(HttpStatusCode.NotFound, []);
 
-    const { type } = await store.dispatch(getAllBackgroundsByProjectId(PROJECT_ID));
+    const { type, payload } = await store.dispatch(getAllBackgroundsByProjectId(PROJECT_ID));
     const { data, loading, error } = store.getState().backgrounds;
 
     expect(type).toBe('backgrounds/getAllBackgroundsByProjectId/rejected');
     expect(loading).toEqual('failed');
     expect(error).toEqual({ message: '', name: '' });
     expect(data).toEqual([]);
+    expect(payload).toBe(
+      "Failed to fetch backgrounds: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
   });
 
   it('should update store on loading getAllBackgroundsByProjectId query', async () => {
diff --git a/src/redux/backgrounds/backgrounds.thunks.ts b/src/redux/backgrounds/backgrounds.thunks.ts
index 3741a1c8ef88c80078adf1462bdeb39807f92e65..18a0c56bcfed6861ffabd3fb944378930dad13c4 100644
--- a/src/redux/backgrounds/backgrounds.thunks.ts
+++ b/src/redux/backgrounds/backgrounds.thunks.ts
@@ -4,17 +4,26 @@ import { MapBackground } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import { apiPath } from '../apiPath';
+import { BACKGROUNDS_FETCHING_ERROR_PREFIX } from './backgrounds.constants';
 
-export const getAllBackgroundsByProjectId = createAsyncThunk(
+export const getAllBackgroundsByProjectId = createAsyncThunk<MapBackground[], string, ThunkConfig>(
   'backgrounds/getAllBackgroundsByProjectId',
-  async (projectId: string): Promise<MapBackground[]> => {
-    const response = await axiosInstance.get<MapBackground[]>(
-      apiPath.getAllBackgroundsByProjectIdQuery(projectId),
-    );
+  async (projectId: string, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstance.get<MapBackground[]>(
+        apiPath.getAllBackgroundsByProjectIdQuery(projectId),
+      );
 
-    const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapBackground));
+      const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapBackground));
 
-    return isDataValid ? response.data : [];
+      return isDataValid ? response.data : [];
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: BACKGROUNDS_FETCHING_ERROR_PREFIX });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/bioEntity/bioEntity.constants.ts b/src/redux/bioEntity/bioEntity.constants.ts
index 3c109ae8c9124dc08e0687a06cd0088029110028..b719afdedbecef74f12b3712ae166430ab7d20f1 100644
--- a/src/redux/bioEntity/bioEntity.constants.ts
+++ b/src/redux/bioEntity/bioEntity.constants.ts
@@ -1,3 +1,6 @@
 export const DEFAULT_BIOENTITY_PARAMS = {
   perfectMatch: false,
 };
+
+export const BIO_ENTITY_FETCHING_ERROR_PREFIX = 'Failed to fetch bio entity';
+export const MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX = 'Failed to fetch multi bio entity';
diff --git a/src/redux/bioEntity/bioEntity.reducers.test.ts b/src/redux/bioEntity/bioEntity.reducers.test.ts
index 52062b406da85f623f5d3a273ead35a9dabb59ae..78482731a21eb2acf4c47279fc272f8a236dec44 100644
--- a/src/redux/bioEntity/bioEntity.reducers.test.ts
+++ b/src/redux/bioEntity/bioEntity.reducers.test.ts
@@ -72,7 +72,7 @@ describe('bioEntity reducer', () => {
       )
       .reply(HttpStatusCode.NotFound, bioEntityResponseFixture);
 
-    const { type } = await store.dispatch(
+    const { type, payload } = await store.dispatch(
       getBioEntity({
         searchQuery: SEARCH_QUERY,
         isPerfectMatch: false,
@@ -84,6 +84,9 @@ describe('bioEntity reducer', () => {
       bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY,
     );
     expect(type).toBe('project/getBioEntityContents/rejected');
+    expect(payload).toBe(
+      "Failed to fetch bio entity: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     expect(bioEnityWithSearchElement).toEqual({
       searchQueryElement: SEARCH_QUERY,
       data: undefined,
diff --git a/src/redux/bioEntity/bioEntity.thunks.test.ts b/src/redux/bioEntity/bioEntity.thunks.test.ts
index 9757ab4b3dee487935863834a79107d980384fa9..f2b54f3abdd5a5e258c51bfc8d224a3877d02fdf 100644
--- a/src/redux/bioEntity/bioEntity.thunks.test.ts
+++ b/src/redux/bioEntity/bioEntity.thunks.test.ts
@@ -55,6 +55,26 @@ describe('bioEntityContents thunks', () => {
       );
       expect(payload).toEqual(undefined);
     });
+    it('should handle error message when getBioEntityContents failed', async () => {
+      mockedAxiosClient
+        .onGet(
+          apiPath.getBioEntityContentsStringWithQuery({
+            searchQuery: SEARCH_QUERY,
+            isPerfectMatch: false,
+          }),
+        )
+        .reply(HttpStatusCode.NotFound, null);
+
+      const { payload } = await store.dispatch(
+        getBioEntity({
+          searchQuery: SEARCH_QUERY,
+          isPerfectMatch: false,
+        }),
+      );
+      expect(payload).toEqual(
+        "Failed to fetch bio entity: The page you're looking for doesn't exist. Please verify the URL and try again.",
+      );
+    });
   });
   describe('getMultiBioEntity', () => {
     it('should return transformed bioEntityContent array', async () => {
diff --git a/src/redux/bioEntity/bioEntity.thunks.ts b/src/redux/bioEntity/bioEntity.thunks.ts
index 32185755ccf261b6aa81edace068e49ba432f872..20c312f52071290648b7dec2949e4bfd1e6e113c 100644
--- a/src/redux/bioEntity/bioEntity.thunks.ts
+++ b/src/redux/bioEntity/bioEntity.thunks.ts
@@ -5,15 +5,21 @@ import { apiPath } from '@/redux/apiPath';
 import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { BioEntityContent, BioEntityResponse } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
+import {
+  BIO_ENTITY_FETCHING_ERROR_PREFIX,
+  MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX,
+} from './bioEntity.constants';
 
 type GetBioEntityProps = PerfectSearchParams;
 
-export const getBioEntity = createAsyncThunk(
-  'project/getBioEntityContents',
-  async ({
-    searchQuery,
-    isPerfectMatch,
-  }: GetBioEntityProps): Promise<BioEntityContent[] | undefined> => {
+export const getBioEntity = createAsyncThunk<
+  BioEntityContent[] | undefined,
+  GetBioEntityProps,
+  ThunkConfig
+>('project/getBioEntityContents', async ({ searchQuery, isPerfectMatch }, { rejectWithValue }) => {
+  try {
     const response = await axiosInstanceNewAPI.get<BioEntityResponse>(
       apiPath.getBioEntityContentsStringWithQuery({ searchQuery, isPerfectMatch }),
     );
@@ -21,30 +27,47 @@ export const getBioEntity = createAsyncThunk(
     const isDataValid = validateDataUsingZodSchema(response.data, bioEntityResponseSchema);
 
     return isDataValid ? response.data.content : undefined;
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({
+      error,
+      prefix: BIO_ENTITY_FETCHING_ERROR_PREFIX,
+    });
+    return rejectWithValue(errorMessage);
+  }
+});
 
 type GetMultiBioEntityProps = PerfectMultiSearchParams;
 type GetMultiBioEntityActions = PayloadAction<BioEntityContent[] | undefined>[];
 
-export const getMultiBioEntity = createAsyncThunk(
+export const getMultiBioEntity = createAsyncThunk<
+  BioEntityContent[],
+  GetMultiBioEntityProps,
+  ThunkConfig
+>(
   'project/getMultiBioEntity',
-  async (
-    { searchQueries, isPerfectMatch }: GetMultiBioEntityProps,
-    { dispatch },
-  ): Promise<BioEntityContent[]> => {
-    const asyncGetBioEntityFunctions = searchQueries.map(searchQuery =>
-      dispatch(getBioEntity({ searchQuery, isPerfectMatch })),
-    );
+  // eslint-disable-next-line consistent-return
+  async ({ searchQueries, isPerfectMatch }, { dispatch, rejectWithValue }) => {
+    try {
+      const asyncGetBioEntityFunctions = searchQueries.map(searchQuery =>
+        dispatch(getBioEntity({ searchQuery, isPerfectMatch })),
+      );
+
+      const bioEntityContentsActions = (await Promise.all(
+        asyncGetBioEntityFunctions,
+      )) as GetMultiBioEntityActions;
 
-    const bioEntityContentsActions = (await Promise.all(
-      asyncGetBioEntityFunctions,
-    )) as GetMultiBioEntityActions;
+      const bioEntityContents = bioEntityContentsActions
+        .map(bioEntityContentsAction => bioEntityContentsAction.payload || [])
+        .flat();
 
-    const bioEntityContents = bioEntityContentsActions
-      .map(bioEntityContentsAction => bioEntityContentsAction.payload || [])
-      .flat();
+      return bioEntityContents;
+    } catch (error) {
+      const errorMessage = getErrorMessage({
+        error,
+        prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX,
+      });
 
-    return bioEntityContents;
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/chemicals/chemicals.constants.ts b/src/redux/chemicals/chemicals.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3311122e0b0eaf0ea055af2892ef537c9807d0b6
--- /dev/null
+++ b/src/redux/chemicals/chemicals.constants.ts
@@ -0,0 +1,2 @@
+export const CHEMICALS_FETCHING_ERROR_PREFIX = 'Failed to fetch chemicals';
+export const MULTI_CHEMICALS_FETCHING_ERROR_PREFIX = 'Failed to fetch multi chemicals';
diff --git a/src/redux/chemicals/chemicals.reducers.test.ts b/src/redux/chemicals/chemicals.reducers.test.ts
index 59a87b20f784e059d63c5ea030274275b2562a6b..9b66afe34421293ef0e89ec2b02b45767c5c151c 100644
--- a/src/redux/chemicals/chemicals.reducers.test.ts
+++ b/src/redux/chemicals/chemicals.reducers.test.ts
@@ -57,7 +57,7 @@ describe('chemicals reducer', () => {
       .onGet(apiPath.getChemicalsStringWithQuery(SEARCH_QUERY))
       .reply(HttpStatusCode.NotFound, chemicalsFixture);
 
-    const { type } = await store.dispatch(getChemicals(SEARCH_QUERY));
+    const { type, payload } = await store.dispatch(getChemicals(SEARCH_QUERY));
     const { data } = store.getState().chemicals;
 
     const chemicalsWithSearchElement = data.find(
@@ -65,6 +65,9 @@ describe('chemicals reducer', () => {
     );
 
     expect(type).toBe('project/getChemicals/rejected');
+    expect(payload).toBe(
+      "Failed to fetch chemicals: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     expect(chemicalsWithSearchElement).toEqual({
       searchQueryElement: SEARCH_QUERY,
       data: undefined,
diff --git a/src/redux/chemicals/chemicals.thunks.test.ts b/src/redux/chemicals/chemicals.thunks.test.ts
index 88926792155e930d39ae396f25733fcb4e1fe099..73cb2d0ef46659c702a4cda23ea6eda640bb871e 100644
--- a/src/redux/chemicals/chemicals.thunks.test.ts
+++ b/src/redux/chemicals/chemicals.thunks.test.ts
@@ -35,5 +35,15 @@ describe('chemicals thunks', () => {
       const { payload } = await store.dispatch(getChemicals(SEARCH_QUERY));
       expect(payload).toEqual(undefined);
     });
+    it('should handle error message when getChemiclas failed ', async () => {
+      mockedAxiosClient
+        .onGet(apiPath.getChemicalsStringWithQuery(SEARCH_QUERY))
+        .reply(HttpStatusCode.Forbidden, { randomProperty: 'randomValue' });
+
+      const { payload } = await store.dispatch(getChemicals(SEARCH_QUERY));
+      expect(payload).toEqual(
+        "Failed to fetch chemicals: Access Forbidden! You don't have permission to access this resource.",
+      );
+    });
   });
 });
diff --git a/src/redux/chemicals/chemicals.thunks.ts b/src/redux/chemicals/chemicals.thunks.ts
index 0afc94db5f8f686b845e8e514082866b18219908..5b25951d7bf7e4ebdaefecdca4afa4bd54501346 100644
--- a/src/redux/chemicals/chemicals.thunks.ts
+++ b/src/redux/chemicals/chemicals.thunks.ts
@@ -2,30 +2,51 @@ import { chemicalSchema } from '@/models/chemicalSchema';
 import { apiPath } from '@/redux/apiPath';
 import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { Chemical } from '@/types/models';
+import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { ThunkConfig } from '@/types/store';
+import {
+  CHEMICALS_FETCHING_ERROR_PREFIX,
+  MULTI_CHEMICALS_FETCHING_ERROR_PREFIX,
+} from './chemicals.constants';
 
-export const getChemicals = createAsyncThunk(
+export const getChemicals = createAsyncThunk<Chemical[] | undefined, string, ThunkConfig>(
   'project/getChemicals',
-  async (searchQuery: string): Promise<Chemical[] | undefined> => {
-    const response = await axiosInstanceNewAPI.get<Chemical[]>(
-      apiPath.getChemicalsStringWithQuery(searchQuery),
-    );
+  async (searchQuery, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstanceNewAPI.get<Chemical[]>(
+        apiPath.getChemicalsStringWithQuery(searchQuery),
+      );
 
-    const isDataValid = validateDataUsingZodSchema(response.data, z.array(chemicalSchema));
+      const isDataValid = validateDataUsingZodSchema(response.data, z.array(chemicalSchema));
 
-    return isDataValid ? response.data : undefined;
+      return isDataValid ? response.data : undefined;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: CHEMICALS_FETCHING_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
-export const getMultiChemicals = createAsyncThunk(
+export const getMultiChemicals = createAsyncThunk<void, string[], ThunkConfig>(
   'project/getMultChemicals',
-  async (searchQueries: string[], { dispatch }): Promise<void> => {
-    const asyncGetChemicalsFunctions = searchQueries.map(searchQuery =>
-      dispatch(getChemicals(searchQuery)),
-    );
+  // eslint-disable-next-line consistent-return
+  async (searchQueries, { dispatch, rejectWithValue }) => {
+    try {
+      const asyncGetChemicalsFunctions = searchQueries.map(searchQuery =>
+        dispatch(getChemicals(searchQuery)),
+      );
 
-    await Promise.all(asyncGetChemicalsFunctions);
+      await Promise.all(asyncGetChemicalsFunctions);
+    } catch (error) {
+      const errorMessage = getErrorMessage({
+        error,
+        prefix: MULTI_CHEMICALS_FETCHING_ERROR_PREFIX,
+      });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/compartmentPathways/comparmentPathways.constants.ts b/src/redux/compartmentPathways/comparmentPathways.constants.ts
index 2bf4d5195d6e6e7fca140310ea21ce69f373da03..cc54322af2521fa94bbe3c5b201b1cd77f5fffd7 100644
--- a/src/redux/compartmentPathways/comparmentPathways.constants.ts
+++ b/src/redux/compartmentPathways/comparmentPathways.constants.ts
@@ -1 +1,3 @@
 export const MAX_NUMBER_OF_IDS_IN_GET_QUERY = 100;
+
+export const COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX = 'Failed to fetch compartment pathways';
diff --git a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts b/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
index 037eefa24fe80a7a82141bdedf7ce5c757e0b9b6..94d445b845aa63f1c45fef92ea66a5a75a05fd00 100644
--- a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
+++ b/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
@@ -112,8 +112,11 @@ describe('compartmentPathways reducer', () => {
     expect(loading).toEqual('pending');
     expect(data).toEqual([]);
 
-    await compartmentPathwaysPromise;
+    const dispatchData = await compartmentPathwaysPromise;
 
+    expect(dispatchData.payload).toBe(
+      "Failed to fetch compartment pathways: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     const { loading: promiseFulfilled, data: dataFulfilled } = store.getState().compartmentPathways;
 
     expect(promiseFulfilled).toEqual('failed');
diff --git a/src/redux/compartmentPathways/compartmentPathways.thunks.ts b/src/redux/compartmentPathways/compartmentPathways.thunks.ts
index e0d69617a704c2361043c98bf1104fb7ced0e827..b8143dbe2627fe7239a9eadf8546497e70b5bbfe 100644
--- a/src/redux/compartmentPathways/compartmentPathways.thunks.ts
+++ b/src/redux/compartmentPathways/compartmentPathways.thunks.ts
@@ -8,7 +8,11 @@ import {
   compartmentPathwaySchema,
 } from '@/models/compartmentPathwaySchema';
 import { z } from 'zod';
-import { MAX_NUMBER_OF_IDS_IN_GET_QUERY } from './comparmentPathways.constants';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import {
+  COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX,
+  MAX_NUMBER_OF_IDS_IN_GET_QUERY,
+} from './comparmentPathways.constants';
 import { apiPath } from '../apiPath';
 
 /** UTILS */
@@ -112,9 +116,18 @@ export const fetchCompartmentPathways = async (
 
 export const getCompartmentPathways = createAsyncThunk(
   'compartmentPathways/getCompartmentPathways',
-  async (modelsIds: number[] | undefined) => {
-    const compartmentIds = await fetchCompartmentPathwaysIds(modelsIds);
-    const comparmentPathways = await fetchCompartmentPathways(compartmentIds);
-    return comparmentPathways;
+  async (modelsIds: number[] | undefined, { rejectWithValue }) => {
+    try {
+      const compartmentIds = await fetchCompartmentPathwaysIds(modelsIds);
+      const comparmentPathways = await fetchCompartmentPathways(compartmentIds);
+
+      return comparmentPathways;
+    } catch (error) {
+      const errorMessage = getErrorMessage({
+        error,
+        prefix: COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX,
+      });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/configuration/configuration.constants.ts b/src/redux/configuration/configuration.constants.ts
index bcf3c906f5ab72e0012749ad77fe2d710e2cd866..9a2762d91efeac7a80edb56d071e2fee999a172d 100644
--- a/src/redux/configuration/configuration.constants.ts
+++ b/src/redux/configuration/configuration.constants.ts
@@ -19,3 +19,7 @@ export const SBGN_ML_HANDLER_NAME_ID = 'SBGN-ML';
 export const PNG_IMAGE_HANDLER_NAME_ID = 'PNG image';
 export const PDF_HANDLER_NAME_ID = 'PDF';
 export const SVG_IMAGE_HANDLER_NAME_ID = 'SVG image';
+
+export const CONFIGURATION_OPTIONS_FETCHING_ERROR_PREFIX = 'Failed to fetch configuration options';
+
+export const CONFIGURATION_FETCHING_ERROR_PREFIX = 'Failed to fetch configuration';
diff --git a/src/redux/configuration/configuration.thunks.ts b/src/redux/configuration/configuration.thunks.ts
index 012e8b1c5184c9ed39c948d76b4124d29dac57d4..8b4db5ea19083cc0f044966eb567cc12610aa66f 100644
--- a/src/redux/configuration/configuration.thunks.ts
+++ b/src/redux/configuration/configuration.thunks.ts
@@ -5,11 +5,20 @@ import { axiosInstance } from '@/services/api/utils/axiosInstance';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { configurationSchema } from '@/models/configurationSchema';
 import { configurationOptionSchema } from '@/models/configurationOptionSchema';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import { apiPath } from '../apiPath';
+import {
+  CONFIGURATION_FETCHING_ERROR_PREFIX,
+  CONFIGURATION_OPTIONS_FETCHING_ERROR_PREFIX,
+} from './configuration.constants';
 
-export const getConfigurationOptions = createAsyncThunk(
-  'configuration/getConfigurationOptions',
-  async (): Promise<ConfigurationOption[] | undefined> => {
+export const getConfigurationOptions = createAsyncThunk<
+  ConfigurationOption[] | undefined,
+  void,
+  ThunkConfig
+>('configuration/getConfigurationOptions', async (_, { rejectWithValue }) => {
+  try {
     const response = await axiosInstance.get<ConfigurationOption[]>(
       apiPath.getConfigurationOptions(),
     );
@@ -20,16 +29,27 @@ export const getConfigurationOptions = createAsyncThunk(
     );
 
     return isDataValid ? response.data : undefined;
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({
+      error,
+      prefix: CONFIGURATION_OPTIONS_FETCHING_ERROR_PREFIX,
+    });
+    return rejectWithValue(errorMessage);
+  }
+});
 
-export const getConfiguration = createAsyncThunk(
+export const getConfiguration = createAsyncThunk<Configuration | undefined, void, ThunkConfig>(
   'configuration/getConfiguration',
-  async (): Promise<Configuration | undefined> => {
-    const response = await axiosInstance.get<Configuration>(apiPath.getConfiguration());
+  async (_, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstance.get<Configuration>(apiPath.getConfiguration());
 
-    const isDataValid = validateDataUsingZodSchema(response.data, configurationSchema);
+      const isDataValid = validateDataUsingZodSchema(response.data, configurationSchema);
 
-    return isDataValid ? response.data : undefined;
+      return isDataValid ? response.data : undefined;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: CONFIGURATION_FETCHING_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/drawer/drawer.constants.ts b/src/redux/drawer/drawer.constants.ts
index 33890a23abf2b03c24b47f53326ea00cf37024f8..bef3fd3d8a0b585baf19e421da3536e218e1403a 100644
--- a/src/redux/drawer/drawer.constants.ts
+++ b/src/redux/drawer/drawer.constants.ts
@@ -19,3 +19,7 @@ export const DRAWER_INITIAL_STATE: DrawerState = {
     currentStep: 0,
   },
 };
+
+export const DRUGS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX = 'Failed to fetch drugs for bio entity';
+export const CHEMICALS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX =
+  'Failed to fetch chemicals for bio entity';
diff --git a/src/redux/drawer/drawer.thunks.ts b/src/redux/drawer/drawer.thunks.ts
index 7e60536f9d9218e75db2e516c8edbf649e43e050..f08955f9c5aafd0d79a7b960fe584abf7b688ac1 100644
--- a/src/redux/drawer/drawer.thunks.ts
+++ b/src/redux/drawer/drawer.thunks.ts
@@ -5,7 +5,13 @@ import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { Chemical, Drug, TargetSearchNameResult } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
+import { ThunkConfig } from '@/types/store';
+import { getErrorMessage } from '@/utils/getErrorMessage';
 import { apiPath } from '../apiPath';
+import {
+  CHEMICALS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX,
+  DRUGS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX,
+} from './drawer.constants';
 
 const QUERY_COLUMN_NAME = 'name';
 
@@ -28,16 +34,25 @@ const getDrugsByName = async (drugName: string): Promise<Drug[]> => {
   return response.data.filter(isDataValid);
 };
 
-export const getDrugsForBioEntityDrawerTarget = createAsyncThunk(
+export const getDrugsForBioEntityDrawerTarget = createAsyncThunk<Drug[], string, ThunkConfig>(
   'drawer/getDrugsForBioEntityDrawerTarget',
-  async (target: string): Promise<Drug[]> => {
-    const drugsNames = await getDrugsNamesForTarget(target);
-    const drugsArrays = await Promise.all(
-      drugsNames.map(({ name }) => getDrugsByName(encodeURIComponent(name))),
-    );
-    const drugs = drugsArrays.flat();
-
-    return drugs;
+  async (target, { rejectWithValue }) => {
+    try {
+      const drugsNames = await getDrugsNamesForTarget(target);
+      const drugsArrays = await Promise.all(
+        drugsNames.map(({ name }) => getDrugsByName(encodeURIComponent(name))),
+      );
+      const drugs = drugsArrays.flat();
+
+      return drugs;
+    } catch (error) {
+      const errorMessage = getErrorMessage({
+        error,
+        prefix: DRUGS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX,
+      });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
@@ -63,9 +78,12 @@ const getChemicalsByName = async (chemicalName: string): Promise<Chemical[]> =>
   return response.data.filter(isDataValid);
 };
 
-export const getChemicalsForBioEntityDrawerTarget = createAsyncThunk(
-  'drawer/getChemicalsForBioEntityDrawerTarget',
-  async (target: string): Promise<Chemical[]> => {
+export const getChemicalsForBioEntityDrawerTarget = createAsyncThunk<
+  Chemical[],
+  string,
+  ThunkConfig
+>('drawer/getChemicalsForBioEntityDrawerTarget', async (target, { rejectWithValue }) => {
+  try {
     const chemicalsNames = await getChemicalsNamesForTarget(target);
     const chemicalsArrays = await Promise.all(
       chemicalsNames.map(({ name }) => getChemicalsByName(encodeURIComponent(name))),
@@ -73,5 +91,12 @@ export const getChemicalsForBioEntityDrawerTarget = createAsyncThunk(
     const chemicals = chemicalsArrays.flat();
 
     return chemicals;
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({
+      error,
+      prefix: CHEMICALS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX,
+    });
+
+    return rejectWithValue(errorMessage);
+  }
+});
diff --git a/src/redux/drugs/drugs.constants.ts b/src/redux/drugs/drugs.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c31cff0fe0dd4e776ff6aa8a3a7044bb7ffedf78
--- /dev/null
+++ b/src/redux/drugs/drugs.constants.ts
@@ -0,0 +1,2 @@
+export const DRUGS_FETCHING_ERROR_PREFIX = 'Failed to fetch drugs';
+export const MULTI_DRUGS_FETCHING_ERROR_PREFIX = 'Failed to fetch multi drugs';
diff --git a/src/redux/drugs/drugs.reducers.test.ts b/src/redux/drugs/drugs.reducers.test.ts
index 3ad034db1d614a691017c221f541dfc39e4b6fcf..f6e6c671bc29975194a163390e717a5bc91275e3 100644
--- a/src/redux/drugs/drugs.reducers.test.ts
+++ b/src/redux/drugs/drugs.reducers.test.ts
@@ -56,12 +56,15 @@ describe('drugs reducer', () => {
       .onGet(apiPath.getDrugsStringWithQuery(SEARCH_QUERY))
       .reply(HttpStatusCode.NotFound, []);
 
-    const { type } = await store.dispatch(getDrugs(SEARCH_QUERY));
+    const { type, payload } = await store.dispatch(getDrugs(SEARCH_QUERY));
     const { data } = store.getState().drugs;
     const drugsWithSearchElement = data.find(
       bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY,
     );
 
+    expect(payload).toBe(
+      "Failed to fetch drugs: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     expect(type).toBe('project/getDrugs/rejected');
     expect(drugsWithSearchElement).toEqual({
       searchQueryElement: SEARCH_QUERY,
diff --git a/src/redux/drugs/drugs.thunks.ts b/src/redux/drugs/drugs.thunks.ts
index 30074e33d6ee751c2f8886e3793050ba84e1d41f..6bd3b532665b877cdd8a7a95263ebdd9ac2bb5de 100644
--- a/src/redux/drugs/drugs.thunks.ts
+++ b/src/redux/drugs/drugs.thunks.ts
@@ -2,30 +2,45 @@ import { drugSchema } from '@/models/drugSchema';
 import { apiPath } from '@/redux/apiPath';
 import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { Drug } from '@/types/models';
+import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { ThunkConfig } from '@/types/store';
+import { DRUGS_FETCHING_ERROR_PREFIX, MULTI_DRUGS_FETCHING_ERROR_PREFIX } from './drugs.constants';
 
-export const getDrugs = createAsyncThunk(
+export const getDrugs = createAsyncThunk<Drug[] | undefined, string, ThunkConfig>(
   'project/getDrugs',
-  async (searchQuery: string): Promise<Drug[] | undefined> => {
-    const response = await axiosInstanceNewAPI.get<Drug[]>(
-      apiPath.getDrugsStringWithQuery(searchQuery),
-    );
+  async (searchQuery: string, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstanceNewAPI.get<Drug[]>(
+        apiPath.getDrugsStringWithQuery(searchQuery),
+      );
 
-    const isDataValid = validateDataUsingZodSchema(response.data, z.array(drugSchema));
+      const isDataValid = validateDataUsingZodSchema(response.data, z.array(drugSchema));
 
-    return isDataValid ? response.data : undefined;
+      return isDataValid ? response.data : undefined;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: DRUGS_FETCHING_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
-export const getMultiDrugs = createAsyncThunk(
+export const getMultiDrugs = createAsyncThunk<void, string[], ThunkConfig>(
   'project/getMultiDrugs',
-  async (searchQueries: string[], { dispatch }): Promise<void> => {
-    const asyncGetDrugsFunctions = searchQueries.map(searchQuery =>
-      dispatch(getDrugs(searchQuery)),
-    );
+  // eslint-disable-next-line consistent-return
+  async (searchQueries, { dispatch, rejectWithValue }) => {
+    try {
+      const asyncGetDrugsFunctions = searchQueries.map(searchQuery =>
+        dispatch(getDrugs(searchQuery)),
+      );
 
-    await Promise.all(asyncGetDrugsFunctions);
+      await Promise.all(asyncGetDrugsFunctions);
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: MULTI_DRUGS_FETCHING_ERROR_PREFIX });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/export/export.constants.ts b/src/redux/export/export.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8f464a4d9241f6d8e4dc875e48c75a4611c16da8
--- /dev/null
+++ b/src/redux/export/export.constants.ts
@@ -0,0 +1,2 @@
+export const ELEMENTS_DOWNLOAD_ERROR_PREFIX = 'Failed to download elements';
+export const NETWORK_DOWNLOAD_ERROR_PREFIX = 'Failed to download network';
diff --git a/src/redux/export/export.reducers.test.ts b/src/redux/export/export.reducers.test.ts
index 894ee98a802339b948da3a12556716284b4aa41d..778aca4f95a58b094b126f449643804fcab85287 100644
--- a/src/redux/export/export.reducers.test.ts
+++ b/src/redux/export/export.reducers.test.ts
@@ -76,7 +76,7 @@ describe('export reducer', () => {
     mockedAxiosClient
       .onPost(apiPath.downloadNetworkCsv())
       .reply(HttpStatusCode.NotFound, undefined);
-    await store.dispatch(
+    const { payload, type } = await store.dispatch(
       downloadNetwork({
         annotations: [],
         columns: [],
@@ -85,8 +85,11 @@ describe('export reducer', () => {
         submaps: [],
       }),
     );
+    expect(type).toBe('export/downloadNetwork/rejected');
+    expect(payload).toBe(
+      "Failed to download network: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     const { loading } = store.getState().export.downloadNetwork;
-
     expect(loading).toEqual('failed');
   });
 
@@ -132,7 +135,7 @@ describe('export reducer', () => {
     mockedAxiosClient
       .onPost(apiPath.downloadElementsCsv())
       .reply(HttpStatusCode.NotFound, undefined);
-    await store.dispatch(
+    const { payload } = await store.dispatch(
       downloadElements({
         annotations: [],
         columns: [],
@@ -144,5 +147,8 @@ describe('export reducer', () => {
     const { loading } = store.getState().export.downloadElements;
 
     expect(loading).toEqual('failed');
+    expect(payload).toEqual(
+      "Failed to download elements: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
   });
 });
diff --git a/src/redux/export/export.thunks.ts b/src/redux/export/export.thunks.ts
index 3a25cd8c40f76e9442d43fa354bd7877d29b4306..bf49e0b04e79e1eea61cac05f2eb79810b23ce55 100644
--- a/src/redux/export/export.thunks.ts
+++ b/src/redux/export/export.thunks.ts
@@ -5,8 +5,11 @@ import { PROJECT_ID } from '@/constants';
 import { ExportNetwork, ExportElements } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { exportNetworkchema, exportElementsSchema } from '@/models/exportSchema';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import { apiPath } from '../apiPath';
 import { downloadFileFromBlob } from './export.utils';
+import { ELEMENTS_DOWNLOAD_ERROR_PREFIX, NETWORK_DOWNLOAD_ERROR_PREFIX } from './export.constants';
 
 type DownloadElementsBodyRequest = {
   columns: string[];
@@ -16,9 +19,13 @@ type DownloadElementsBodyRequest = {
   excludedCompartmentIds: number[];
 };
 
-export const downloadElements = createAsyncThunk(
-  'export/downloadElements',
-  async (data: DownloadElementsBodyRequest): Promise<void> => {
+export const downloadElements = createAsyncThunk<
+  undefined,
+  DownloadElementsBodyRequest,
+  ThunkConfig
+  // eslint-disable-next-line consistent-return
+>('export/downloadElements', async (data, { rejectWithValue }) => {
+  try {
     const response = await axiosInstanceNewAPI.post<ExportElements>(
       apiPath.downloadElementsCsv(),
       data,
@@ -32,8 +39,12 @@ export const downloadElements = createAsyncThunk(
     if (isDataValid) {
       downloadFileFromBlob(response.data, `${PROJECT_ID}-elementExport.csv`);
     }
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({ error, prefix: ELEMENTS_DOWNLOAD_ERROR_PREFIX });
+
+    return rejectWithValue(errorMessage);
+  }
+});
 
 type DownloadNetworkBodyRequest = {
   columns: string[];
@@ -43,21 +54,28 @@ type DownloadNetworkBodyRequest = {
   excludedCompartmentIds: number[];
 };
 
-export const downloadNetwork = createAsyncThunk(
+export const downloadNetwork = createAsyncThunk<undefined, DownloadNetworkBodyRequest, ThunkConfig>(
   'export/downloadNetwork',
-  async (data: DownloadNetworkBodyRequest): Promise<void> => {
-    const response = await axiosInstanceNewAPI.post<ExportNetwork>(
-      apiPath.downloadNetworkCsv(),
-      data,
-      {
-        withCredentials: true,
-      },
-    );
+  // eslint-disable-next-line consistent-return
+  async (data, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstanceNewAPI.post<ExportNetwork>(
+        apiPath.downloadNetworkCsv(),
+        data,
+        {
+          withCredentials: true,
+        },
+      );
 
-    const isDataValid = validateDataUsingZodSchema(response.data, exportNetworkchema);
+      const isDataValid = validateDataUsingZodSchema(response.data, exportNetworkchema);
 
-    if (isDataValid) {
-      downloadFileFromBlob(response.data, `${PROJECT_ID}-networkExport.csv`);
+      if (isDataValid) {
+        downloadFileFromBlob(response.data, `${PROJECT_ID}-networkExport.csv`);
+      }
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: NETWORK_DOWNLOAD_ERROR_PREFIX });
+
+      return rejectWithValue(errorMessage);
     }
   },
 );
diff --git a/src/redux/map/map.constants.ts b/src/redux/map/map.constants.ts
index 27a63ef2a593b6e1fd2f031870ae4b489ba6ba25..70126c71e6dbd43d510b1662096b9178d20452f1 100644
--- a/src/redux/map/map.constants.ts
+++ b/src/redux/map/map.constants.ts
@@ -54,3 +54,11 @@ export const MAP_INITIAL_STATE: MapState = {
   error: { name: '', message: '' },
   openedMaps: OPENED_MAPS_INITIAL_STATE,
 };
+
+export const INIT_MAP_SIZE_MODEL_ID_ERROR_PREFIX = 'Failed to initialize map size and model ID';
+
+export const INIT_MAP_POSITION_ERROR_PREFIX = 'Failed to initialize map position';
+
+export const INIT_MAP_BACKGROUND_ERROR_PREFIX = 'Failed to initialize map background';
+
+export const INIT_OPENED_MAPS_ERROR_PREFIX = 'Failed to initialize opened maps';
diff --git a/src/redux/map/map.thunks.ts b/src/redux/map/map.thunks.ts
index e9c3c7ae8703638ab1942c366cfb6ecc32006955..05b675bba64d223d63cab0865e8692f5f9620da4 100644
--- a/src/redux/map/map.thunks.ts
+++ b/src/redux/map/map.thunks.ts
@@ -5,6 +5,8 @@ import { QueryData } from '@/types/query';
 import { DEFAULT_ZOOM } from '@/constants/map';
 import { getPointMerged } from '@/utils/object/getPointMerged';
 import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import type { AppDispatch, RootState } from '../store';
 import {
   InitMapBackgroundActionPayload,
@@ -26,7 +28,14 @@ import {
   modelByIdSelector,
   modelsDataSelector,
 } from '../models/models.selectors';
-import { DEFAULT_POSITION, MAIN_MAP } from './map.constants';
+import {
+  DEFAULT_POSITION,
+  MAIN_MAP,
+  INIT_MAP_BACKGROUND_ERROR_PREFIX,
+  INIT_MAP_POSITION_ERROR_PREFIX,
+  INIT_MAP_SIZE_MODEL_ID_ERROR_PREFIX,
+  INIT_OPENED_MAPS_ERROR_PREFIX,
+} from './map.constants';
 
 /** UTILS - in the same file because of dependancy cycle */
 
@@ -135,47 +144,62 @@ export const getOpenedMaps = (state: RootState, queryData: QueryData): OppenedMa
 export const initMapSizeAndModelId = createAsyncThunk<
   InitMapSizeAndModelIdActionPayload,
   InitMapSizeAndModelIdParams,
-  { dispatch: AppDispatch; state: RootState }
->(
-  'map/initMapSizeAndModelId',
-  async ({ queryData }, { getState }): Promise<InitMapSizeAndModelIdActionPayload> => {
+  { dispatch: AppDispatch; state: RootState } & ThunkConfig
+>('map/initMapSizeAndModelId', async ({ queryData }, { getState, rejectWithValue }) => {
+  try {
     const state = getState();
 
     return getInitMapSizeAndModelId(state, queryData);
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({ error, prefix: INIT_MAP_SIZE_MODEL_ID_ERROR_PREFIX });
+
+    return rejectWithValue(errorMessage);
+  }
+});
 
 export const initMapPosition = createAsyncThunk<
   InitMapPositionActionPayload,
   InitMapPositionParams,
-  { dispatch: AppDispatch; state: RootState }
->(
-  'map/initMapPosition',
-  async ({ queryData }, { getState }): Promise<InitMapPositionActionPayload> => {
+  { dispatch: AppDispatch; state: RootState } & ThunkConfig
+>('map/initMapPosition', async ({ queryData }, { getState, rejectWithValue }) => {
+  try {
     const state = getState();
 
     return getInitMapPosition(state, queryData);
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({ error, prefix: INIT_MAP_POSITION_ERROR_PREFIX });
+
+    return rejectWithValue(errorMessage);
+  }
+});
 
 export const initMapBackground = createAsyncThunk<
   InitMapBackgroundActionPayload,
   InitMapBackgroundParams,
-  { dispatch: AppDispatch; state: RootState }
->(
-  'map/initMapBackground',
-  async ({ queryData }, { getState }): Promise<InitMapBackgroundActionPayload> => {
+  { dispatch: AppDispatch; state: RootState } & ThunkConfig
+>('map/initMapBackground', async ({ queryData }, { getState, rejectWithValue }) => {
+  try {
     const state = getState();
     return getBackgroundId(state, queryData);
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({ error, prefix: INIT_MAP_BACKGROUND_ERROR_PREFIX });
+
+    return rejectWithValue(errorMessage);
+  }
+});
 
 export const initOpenedMaps = createAsyncThunk<
   InitOpenedMapsActionPayload,
   InitOpenedMapsProps,
-  { dispatch: AppDispatch; state: RootState }
->('appInit/initOpenedMaps', async ({ queryData }, { getState }): Promise<OppenedMap[]> => {
-  const state = getState();
+  { dispatch: AppDispatch; state: RootState } & ThunkConfig
+>('appInit/initOpenedMaps', async ({ queryData }, { getState, rejectWithValue }) => {
+  try {
+    const state = getState();
+
+    return getOpenedMaps(state, queryData);
+  } catch (error) {
+    const errorMessage = getErrorMessage({ error, prefix: INIT_OPENED_MAPS_ERROR_PREFIX });
 
-  return getOpenedMaps(state, queryData);
+    return rejectWithValue(errorMessage);
+  }
 });
diff --git a/src/redux/middlewares/error.middleware.test.ts b/src/redux/middlewares/error.middleware.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7662714e2f08a2dccd3a6329db08716d0103bc2d
--- /dev/null
+++ b/src/redux/middlewares/error.middleware.test.ts
@@ -0,0 +1,87 @@
+import { showToast } from '@/utils/showToast';
+import { errorMiddlewareListener } from './error.middleware';
+
+jest.mock('../../utils/showToast', () => ({
+  showToast: jest.fn(),
+}));
+
+describe('errorMiddlewareListener', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should show toast with error message when action is rejected with value', async () => {
+    const action = {
+      type: 'action/rejected',
+      payload: 'Error message',
+      meta: {
+        requestId: '421',
+        rejectedWithValue: true,
+        requestStatus: 'rejected',
+      },
+    };
+    await errorMiddlewareListener(action);
+    expect(showToast).toHaveBeenCalledWith({ type: 'error', message: 'Error message' });
+  });
+
+  it('should show toast with unknown error when action is rejected without value', async () => {
+    const action = {
+      type: 'action/rejected',
+      payload: null,
+      meta: {
+        requestId: '421',
+        rejectedWithValue: true,
+        requestStatus: 'rejected',
+      },
+    };
+    await errorMiddlewareListener(action);
+    expect(showToast).toHaveBeenCalledWith({
+      type: 'error',
+      message: 'An unknown error occurred. Please try again later.',
+    });
+  });
+
+  it('should not show toast when action is not rejected', async () => {
+    const action = {
+      type: 'action/loading',
+      payload: null,
+      meta: {
+        requestId: '421',
+        requestStatus: 'fulfilled',
+      },
+    };
+    await errorMiddlewareListener(action);
+    expect(showToast).not.toHaveBeenCalled();
+  });
+
+  it('should show toast with unknown error when action payload is not a string', async () => {
+    const action = {
+      type: 'action/rejected',
+      payload: {},
+      meta: {
+        requestId: '421',
+        rejectedWithValue: true,
+        requestStatus: 'rejected',
+      },
+    };
+    await errorMiddlewareListener(action);
+    expect(showToast).toHaveBeenCalledWith({
+      type: 'error',
+      message: 'An unknown error occurred. Please try again later.',
+    });
+  });
+
+  it('should show toast with custom message when action payload is a string', async () => {
+    const action = {
+      type: 'action/rejected',
+      payload: 'Failed to fetch',
+      meta: {
+        requestId: '421',
+        rejectedWithValue: true,
+        requestStatus: 'rejected',
+      },
+    };
+    await errorMiddlewareListener(action);
+    expect(showToast).toHaveBeenCalledWith({ type: 'error', message: 'Failed to fetch' });
+  });
+});
diff --git a/src/redux/middlewares/error.middleware.ts b/src/redux/middlewares/error.middleware.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0ba6a0f75452822908c449ba4d3dcb0ac59dddd9
--- /dev/null
+++ b/src/redux/middlewares/error.middleware.ts
@@ -0,0 +1,34 @@
+import type { AppStartListening } from '@/redux/store';
+import { UNKNOWN_ERROR } from '@/utils/getErrorMessage/getErrorMessage.constants';
+import { showToast } from '@/utils/showToast';
+import {
+  Action,
+  createListenerMiddleware,
+  isRejected,
+  isRejectedWithValue,
+} from '@reduxjs/toolkit';
+
+export const errorListenerMiddleware = createListenerMiddleware();
+
+const startListening = errorListenerMiddleware.startListening as AppStartListening;
+
+export const errorMiddlewareListener = async (action: Action): Promise<void> => {
+  if (isRejectedWithValue(action)) {
+    let message: string;
+    if (typeof action.payload === 'string') {
+      message = action.payload;
+    } else {
+      message = UNKNOWN_ERROR;
+    }
+
+    showToast({
+      type: 'error',
+      message,
+    });
+  }
+};
+
+startListening({
+  matcher: isRejected,
+  effect: errorMiddlewareListener,
+});
diff --git a/src/redux/models/models.constants.ts b/src/redux/models/models.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8855ad369fa1edf8e68a99b6171983a52ea42793
--- /dev/null
+++ b/src/redux/models/models.constants.ts
@@ -0,0 +1 @@
+export const MODELS_FETCHING_ERROR_PREFIX = 'Failed to fetch models';
diff --git a/src/redux/models/models.reducers.test.ts b/src/redux/models/models.reducers.test.ts
index 1677afdfd86b83f6a1ea7834cbc15ceb0d71018e..fc6e0af1e28e47a3bb0e2ed3a38186549c053907 100644
--- a/src/redux/models/models.reducers.test.ts
+++ b/src/redux/models/models.reducers.test.ts
@@ -44,10 +44,13 @@ describe('models reducer', () => {
   it('should update store after failed getModels query', async () => {
     mockedAxiosClient.onGet(apiPath.getModelsString()).reply(HttpStatusCode.NotFound, []);
 
-    const { type } = await store.dispatch(getModels());
+    const { type, payload } = await store.dispatch(getModels());
     const { data, loading, error } = store.getState().models;
 
     expect(type).toBe('project/getModels/rejected');
+    expect(payload).toBe(
+      "Failed to fetch models: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     expect(loading).toEqual('failed');
     expect(error).toEqual({ message: '', name: '' });
     expect(data).toEqual([]);
diff --git a/src/redux/models/models.thunks.ts b/src/redux/models/models.thunks.ts
index 5880ddcd4cd8f2494790f321e05fac0ab0c25021..2e0fd68d89e09cff7b66e6c5e1aefff3acc15486 100644
--- a/src/redux/models/models.thunks.ts
+++ b/src/redux/models/models.thunks.ts
@@ -2,17 +2,26 @@ import { mapModelSchema } from '@/models/modelSchema';
 import { apiPath } from '@/redux/apiPath';
 import { axiosInstance } from '@/services/api/utils/axiosInstance';
 import { MapModel } from '@/types/models';
+import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { ThunkConfig } from '@/types/store';
+import { MODELS_FETCHING_ERROR_PREFIX } from './models.constants';
 
-export const getModels = createAsyncThunk(
+export const getModels = createAsyncThunk<MapModel[] | undefined, void, ThunkConfig>(
   'project/getModels',
-  async (): Promise<MapModel[] | undefined> => {
-    const response = await axiosInstance.get<MapModel[]>(apiPath.getModelsString());
+  async (_, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstance.get<MapModel[]>(apiPath.getModelsString());
 
-    const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapModelSchema));
+      const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapModelSchema));
 
-    return isDataValid ? response.data : undefined;
+      return isDataValid ? response.data : undefined;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: MODELS_FETCHING_ERROR_PREFIX });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/overlayBioEntity/overlayBioEntity.constants.ts b/src/redux/overlayBioEntity/overlayBioEntity.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5b9a636a6b2b287f4ea7f1e259df1b9375df4c1c
--- /dev/null
+++ b/src/redux/overlayBioEntity/overlayBioEntity.constants.ts
@@ -0,0 +1,4 @@
+export const OVERLAY_BIO_ENTITY_FETCHING_ERROR_PREFIX = 'Failed to fetch overlay bio entity';
+export const OVERLAY_BIO_ENTITY_ALL_MODELS_FETCHING_ERROR_PREFIX =
+  'Failed to fetch overlay bio entity for all models';
+export const INIT_OVERLAYS_ERROR_PREFIX = 'Failed to initialize overlays';
diff --git a/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts b/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts
index 1fed7a9709ff7807203437b18647776fbd667ee1..30222f300c8a31f6d6104e23634c9d9b0d6d33ac 100644
--- a/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts
+++ b/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts
@@ -3,6 +3,8 @@ import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { OverlayBioEntity } from '@/types/models';
 import { OverlayBioEntityRender } from '@/types/OLrendering';
 import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import {
   getValidOverlayBioEntities,
   parseOverlayBioEntityToOlRenderingFormat,
@@ -13,18 +15,23 @@ import type { RootState } from '../store';
 import { setMapBackground } from '../map/map.slice';
 import { emptyBackgroundIdSelector } from '../backgrounds/background.selectors';
 import { overlaySelector, userOverlaySelector } from '../overlays/overlays.selectors';
+import {
+  INIT_OVERLAYS_ERROR_PREFIX,
+  OVERLAY_BIO_ENTITY_ALL_MODELS_FETCHING_ERROR_PREFIX,
+  OVERLAY_BIO_ENTITY_FETCHING_ERROR_PREFIX,
+} from './overlayBioEntity.constants';
 
 type GetOverlayBioEntityThunkProps = {
   overlayId: number;
   modelId: number;
 };
 
-export const getOverlayBioEntity = createAsyncThunk(
-  'overlayBioEntity/getOverlayBioEntity',
-  async ({
-    overlayId,
-    modelId,
-  }: GetOverlayBioEntityThunkProps): Promise<OverlayBioEntityRender[] | undefined> => {
+export const getOverlayBioEntity = createAsyncThunk<
+  OverlayBioEntityRender[] | undefined,
+  GetOverlayBioEntityThunkProps,
+  ThunkConfig
+>('overlayBioEntity/getOverlayBioEntity', async ({ overlayId, modelId }, { rejectWithValue }) => {
+  try {
     const response = await axiosInstanceNewAPI.get<OverlayBioEntity[]>(
       apiPath.getOverlayBioEntity({ overlayId, modelId }),
       {
@@ -39,34 +46,55 @@ export const getOverlayBioEntity = createAsyncThunk(
     }
 
     return undefined;
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({
+      error,
+      prefix: OVERLAY_BIO_ENTITY_FETCHING_ERROR_PREFIX,
+    });
+
+    return rejectWithValue(errorMessage);
+  }
+});
 
 type GetOverlayBioEntityForAllModelsThunkProps = { overlayId: number };
 
 export const getOverlayBioEntityForAllModels = createAsyncThunk<
   void,
   GetOverlayBioEntityForAllModelsThunkProps,
-  { state: RootState }
+  { state: RootState } & ThunkConfig
 >(
   'overlayBioEntity/getOverlayBioEntityForAllModels',
-  async ({ overlayId }, { dispatch, getState }): Promise<void> => {
-    const state = getState();
-    const modelsIds = modelsIdsSelector(state);
+  // eslint-disable-next-line consistent-return
+  async ({ overlayId }, { dispatch, getState, rejectWithValue }) => {
+    try {
+      const state = getState();
+      const modelsIds = modelsIdsSelector(state);
 
-    const asyncGetOverlayBioEntityFunctions = modelsIds.map(id =>
-      dispatch(getOverlayBioEntity({ overlayId, modelId: id })),
-    );
+      const asyncGetOverlayBioEntityFunctions = modelsIds.map(id =>
+        dispatch(getOverlayBioEntity({ overlayId, modelId: id })),
+      );
 
-    await Promise.all(asyncGetOverlayBioEntityFunctions);
+      await Promise.all(asyncGetOverlayBioEntityFunctions);
+    } catch (error) {
+      const errorMessage = getErrorMessage({
+        error,
+        prefix: OVERLAY_BIO_ENTITY_ALL_MODELS_FETCHING_ERROR_PREFIX,
+      });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
 type GetInitOverlaysProps = { overlaysId: number[] };
 
-export const getInitOverlays = createAsyncThunk<void, GetInitOverlaysProps, { state: RootState }>(
-  'appInit/getInitOverlays',
-  async ({ overlaysId }, { dispatch, getState }): Promise<void> => {
+export const getInitOverlays = createAsyncThunk<
+  void,
+  GetInitOverlaysProps,
+  { state: RootState } & ThunkConfig
+  // eslint-disable-next-line consistent-return
+>('appInit/getInitOverlays', async ({ overlaysId }, { dispatch, getState, rejectWithValue }) => {
+  try {
     const state = getState();
 
     const emptyBackgroundId = emptyBackgroundIdSelector(state);
@@ -86,5 +114,9 @@ export const getInitOverlays = createAsyncThunk<void, GetInitOverlaysProps, { st
 
       dispatch(getOverlayBioEntityForAllModels({ overlayId: id }));
     });
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({ error, prefix: INIT_OVERLAYS_ERROR_PREFIX });
+
+    return rejectWithValue(errorMessage);
+  }
+});
diff --git a/src/redux/overlays/overlays.constants.ts b/src/redux/overlays/overlays.constants.ts
index dda564cda0098e449d5adadb219d86b8320378e4..fa7efe227279b72b850a0e256771b6bb6288163b 100644
--- a/src/redux/overlays/overlays.constants.ts
+++ b/src/redux/overlays/overlays.constants.ts
@@ -1,2 +1,11 @@
 /* eslint-disable no-magic-numbers */
 export const CHUNK_SIZE = 65535 * 8;
+
+export const OVERLAYS_FETCHING_ERROR_PREFIX = 'Failed to fetch overlays';
+export const USER_OVERLAY_ADD_ERROR_PREFIX = 'Failed to add user overlay';
+export const USER_OVERLAY_ADD_SUCCESS_MESSAGE = 'User overlay added successfully';
+export const USER_OVERLAYS_FETCHING_ERROR_PREFIX = 'Failed to fetch user overlays';
+export const USER_OVERLAY_UPDATE_ERROR_PREFIX = 'Failed to update user overlay';
+export const USER_OVERLAY_UPDATE_SUCCESS_MESSAGE = 'User overlay updated successfully';
+export const USER_OVERLAY_REMOVE_ERROR_PREFIX = 'Failed to remove user overlay';
+export const USER_OVERLAY_REMOVE_SUCCESS_MESSAGE = 'User overlay removed successfully';
diff --git a/src/redux/overlays/overlays.reducers.test.ts b/src/redux/overlays/overlays.reducers.test.ts
index f774974f526383c5ed83a27c9343f7a758e2478c..38b4652f0f0c29e09c3917d9de1160f9dc27fc4a 100644
--- a/src/redux/overlays/overlays.reducers.test.ts
+++ b/src/redux/overlays/overlays.reducers.test.ts
@@ -80,10 +80,13 @@ describe('overlays reducer', () => {
       .onGet(apiPath.getAllOverlaysByProjectIdQuery(PROJECT_ID, { publicOverlay: true }))
       .reply(HttpStatusCode.NotFound, []);
 
-    const { type } = await store.dispatch(getAllPublicOverlaysByProjectId(PROJECT_ID));
+    const { type, payload } = await store.dispatch(getAllPublicOverlaysByProjectId(PROJECT_ID));
     const { data, loading, error } = store.getState().overlays;
 
     expect(type).toBe('overlays/getAllPublicOverlaysByProjectId/rejected');
+    expect(payload).toBe(
+      "Failed to fetch overlays: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     expect(loading).toEqual('failed');
     expect(error).toEqual({ message: '', name: '' });
     expect(data).toEqual([]);
diff --git a/src/redux/overlays/overlays.thunks.ts b/src/redux/overlays/overlays.thunks.ts
index 6331642162ed8cfcc3b37f756bcbafbabf74a1a2..4b1fa460e4d60e8604d9bf36a351597d9db3929f 100644
--- a/src/redux/overlays/overlays.thunks.ts
+++ b/src/redux/overlays/overlays.thunks.ts
@@ -11,51 +11,75 @@ import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
 import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
+import { showToast } from '@/utils/showToast';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import { apiPath } from '../apiPath';
-import { CHUNK_SIZE } from './overlays.constants';
+import {
+  CHUNK_SIZE,
+  OVERLAYS_FETCHING_ERROR_PREFIX,
+  USER_OVERLAYS_FETCHING_ERROR_PREFIX,
+  USER_OVERLAY_ADD_ERROR_PREFIX,
+  USER_OVERLAY_ADD_SUCCESS_MESSAGE,
+  USER_OVERLAY_REMOVE_ERROR_PREFIX,
+  USER_OVERLAY_REMOVE_SUCCESS_MESSAGE,
+  USER_OVERLAY_UPDATE_ERROR_PREFIX,
+  USER_OVERLAY_UPDATE_SUCCESS_MESSAGE,
+} from './overlays.constants';
 import { closeModal } from '../modal/modal.slice';
 import type { RootState } from '../store';
 
-export const getAllPublicOverlaysByProjectId = createAsyncThunk(
+export const getAllPublicOverlaysByProjectId = createAsyncThunk<MapOverlay[], string, ThunkConfig>(
   'overlays/getAllPublicOverlaysByProjectId',
-  async (projectId: string): Promise<MapOverlay[]> => {
-    const response = await axiosInstance.get<MapOverlay[]>(
-      apiPath.getAllOverlaysByProjectIdQuery(projectId, { publicOverlay: true }),
-    );
+  async (projectId: string, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstance.get<MapOverlay[]>(
+        apiPath.getAllOverlaysByProjectIdQuery(projectId, { publicOverlay: true }),
+      );
 
-    const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapOverlay));
+      const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapOverlay));
 
-    return isDataValid ? response.data : [];
+      return isDataValid ? response.data : [];
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: OVERLAYS_FETCHING_ERROR_PREFIX });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
-export const getAllUserOverlaysByCreator = createAsyncThunk(
+export const getAllUserOverlaysByCreator = createAsyncThunk<MapOverlay[], void, ThunkConfig>(
   'overlays/getAllUserOverlaysByCreator',
-  async (_, { getState }): Promise<MapOverlay[]> => {
-    const state = getState() as RootState;
-    const creator = state.user.login;
-    if (!creator) return [];
-
-    const response = await axiosInstance<MapOverlay[]>(
-      apiPath.getAllUserOverlaysByCreatorQuery({
-        creator,
-        publicOverlay: false,
-      }),
-      {
-        withCredentials: true,
-      },
-    );
+  async (_, { getState, rejectWithValue }) => {
+    try {
+      const state = getState() as RootState;
+      const creator = state.user.login;
+      if (!creator) return [];
+
+      const response = await axiosInstance<MapOverlay[]>(
+        apiPath.getAllUserOverlaysByCreatorQuery({
+          creator,
+          publicOverlay: false,
+        }),
+        {
+          withCredentials: true,
+        },
+      );
 
-    const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapOverlay));
+      const isDataValid = validateDataUsingZodSchema(response.data, z.array(mapOverlay));
 
-    const sortByOrder = (userOverlayA: MapOverlay, userOverlayB: MapOverlay): number => {
-      if (userOverlayA.order > userOverlayB.order) return 1;
-      return -1;
-    };
+      const sortByOrder = (userOverlayA: MapOverlay, userOverlayB: MapOverlay): number => {
+        if (userOverlayA.order > userOverlayB.order) return 1;
+        return -1;
+      };
 
-    const sortedUserOverlays = response.data.sort(sortByOrder);
+      const sortedUserOverlays = response.data.sort(sortByOrder);
 
-    return isDataValid ? sortedUserOverlays : [];
+      return isDataValid ? sortedUserOverlays : [];
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: USER_OVERLAYS_FETCHING_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
@@ -168,68 +192,93 @@ type AddOverlayArgs = {
   projectId: string;
 };
 
-export const addOverlay = createAsyncThunk(
+export const addOverlay = createAsyncThunk<undefined, AddOverlayArgs, ThunkConfig>(
   'overlays/addOverlay',
   async (
-    { filename, content, description, name, type, projectId }: AddOverlayArgs,
-    { dispatch },
-  ): Promise<void> => {
-    const createdFile = await createFile({
-      filename,
-      content,
-    });
-
-    await uploadContent({
-      createdFile,
-      overlayContent: content,
-    });
-
-    await creteOverlay({
-      createdFile,
-      description,
-      name,
-      type,
-      projectId,
-    });
-
-    dispatch(getAllUserOverlaysByCreator());
+    { filename, content, description, name, type, projectId },
+    { rejectWithValue, dispatch },
+    // eslint-disable-next-line consistent-return
+  ) => {
+    try {
+      const createdFile = await createFile({
+        filename,
+        content,
+      });
+
+      await uploadContent({
+        createdFile,
+        overlayContent: content,
+      });
+
+      await creteOverlay({
+        createdFile,
+        description,
+        name,
+        type,
+        projectId,
+      });
+
+      await dispatch(getAllUserOverlaysByCreator());
+
+      showToast({ type: 'success', message: USER_OVERLAY_ADD_SUCCESS_MESSAGE });
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: USER_OVERLAY_ADD_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
-export const updateOverlays = createAsyncThunk(
+export const updateOverlays = createAsyncThunk<undefined, MapOverlay[], ThunkConfig>(
   'overlays/updateOverlays',
-  async (userOverlays: MapOverlay[]): Promise<void> => {
-    const userOverlaysPromises = userOverlays.map(userOverlay =>
-      axiosInstance.patch<MapOverlay>(
-        apiPath.updateOverlay(userOverlay.idObject),
-        {
-          overlay: userOverlay,
-        },
-        {
-          withCredentials: true,
-        },
-      ),
-    );
-
-    const userOverlaysResponses = await Promise.all(userOverlaysPromises);
-
-    const updatedUserOverlays = userOverlaysResponses.map(
-      updatedUserOverlay => updatedUserOverlay.data,
-    );
-
-    validateDataUsingZodSchema(updatedUserOverlays, z.array(mapOverlay));
+  // eslint-disable-next-line consistent-return
+  async (userOverlays, { rejectWithValue }) => {
+    try {
+      const userOverlaysPromises = userOverlays.map(userOverlay =>
+        axiosInstance.patch<MapOverlay>(
+          apiPath.updateOverlay(userOverlay.idObject),
+          {
+            overlay: userOverlay,
+          },
+          {
+            withCredentials: true,
+          },
+        ),
+      );
+
+      const userOverlaysResponses = await Promise.all(userOverlaysPromises);
+
+      const updatedUserOverlays = userOverlaysResponses.map(
+        updatedUserOverlay => updatedUserOverlay.data,
+      );
+
+      validateDataUsingZodSchema(updatedUserOverlays, z.array(mapOverlay));
+
+      showToast({ type: 'success', message: USER_OVERLAY_UPDATE_SUCCESS_MESSAGE });
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: USER_OVERLAY_UPDATE_ERROR_PREFIX });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
-export const removeOverlay = createAsyncThunk(
+export const removeOverlay = createAsyncThunk<undefined, { overlayId: number }, ThunkConfig>(
   'overlays/removeOverlay',
-  async ({ overlayId }: { overlayId: number }, thunkApi): Promise<void> => {
-    await axiosInstance.delete(apiPath.removeOverlay(overlayId), {
-      withCredentials: true,
-    });
+  // eslint-disable-next-line consistent-return
+  async ({ overlayId }, { dispatch, rejectWithValue }) => {
+    try {
+      await axiosInstance.delete(apiPath.removeOverlay(overlayId), {
+        withCredentials: true,
+      });
+
+      PluginsEventBus.dispatchEvent('onRemoveDataOverlay', overlayId);
+      await dispatch(getAllUserOverlaysByCreator());
+      dispatch(closeModal());
 
-    PluginsEventBus.dispatchEvent('onRemoveDataOverlay', overlayId);
-    await thunkApi.dispatch(getAllUserOverlaysByCreator());
-    thunkApi.dispatch(closeModal());
+      showToast({ type: 'success', message: USER_OVERLAY_REMOVE_SUCCESS_MESSAGE });
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: USER_OVERLAY_REMOVE_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/plugins/plugins.constants.ts b/src/redux/plugins/plugins.constants.ts
index cdd616c5580b1f31c7837bfc2cc84e3d1d7940cb..812e85036ae0588e93006646aa700663aa88c0f5 100644
--- a/src/redux/plugins/plugins.constants.ts
+++ b/src/redux/plugins/plugins.constants.ts
@@ -15,3 +15,7 @@ export const PLUGINS_INITIAL_STATE: PluginsState = {
     currentPluginHash: undefined,
   },
 };
+
+export const PLUGIN_REGISTER_ERROR_PREFIX = 'Failed to register plugin';
+export const PLUGIN_INIT_FETCHING_ERROR_PREFIX = 'Failed to initialize fetching plugin';
+export const PLUGIN_FETCHING_ALL_ERROR_PREFIX = 'Failed to fetch all plugins';
diff --git a/src/redux/plugins/plugins.reducers.test.ts b/src/redux/plugins/plugins.reducers.test.ts
index edc59097d4d53fe239bace4d11948391b3857847..885f421215d099663d278f47f5498a04050ba6a3 100644
--- a/src/redux/plugins/plugins.reducers.test.ts
+++ b/src/redux/plugins/plugins.reducers.test.ts
@@ -69,7 +69,9 @@ describe('plugins reducer', () => {
     );
 
     expect(type).toBe('plugins/registerPlugin/rejected');
-    expect(payload).toEqual(undefined);
+    expect(payload).toEqual(
+      "Failed to register plugin: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     const { data, pluginsId } = store.getState().plugins.activePlugins;
 
     expect(data).toEqual({});
diff --git a/src/redux/plugins/plugins.thunks.ts b/src/redux/plugins/plugins.thunks.ts
index afe657f91d3473aa7cca56d7c2a90a1304a6d129..1d69a6cbb318e9a02a78ce882e9c638199ebd324 100644
--- a/src/redux/plugins/plugins.thunks.ts
+++ b/src/redux/plugins/plugins.thunks.ts
@@ -5,7 +5,14 @@ import type { MinervaPlugin } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import axios from 'axios';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import { apiPath } from '../apiPath';
+import {
+  PLUGIN_FETCHING_ALL_ERROR_PREFIX,
+  PLUGIN_INIT_FETCHING_ERROR_PREFIX,
+  PLUGIN_REGISTER_ERROR_PREFIX,
+} from './plugins.constants';
 
 type RegisterPlugin = {
   hash: string;
@@ -15,38 +22,41 @@ type RegisterPlugin = {
   isPublic: boolean;
 };
 
-export const registerPlugin = createAsyncThunk(
+export const registerPlugin = createAsyncThunk<
+  MinervaPlugin | undefined,
+  RegisterPlugin,
+  ThunkConfig
+>(
   'plugins/registerPlugin',
-  async ({
-    hash,
-    isPublic,
-    pluginName,
-    pluginUrl,
-    pluginVersion,
-  }: RegisterPlugin): Promise<MinervaPlugin | undefined> => {
-    const payload = {
-      hash,
-      url: pluginUrl,
-      name: pluginName,
-      version: pluginVersion,
-      isPublic: isPublic.toString(),
-    } as const;
+  async ({ hash, isPublic, pluginName, pluginUrl, pluginVersion }, { rejectWithValue }) => {
+    try {
+      const payload = {
+        hash,
+        url: pluginUrl,
+        name: pluginName,
+        version: pluginVersion,
+        isPublic: isPublic.toString(),
+      } as const;
 
-    const response = await axiosInstance.post<MinervaPlugin>(
-      apiPath.registerPluign(),
-      new URLSearchParams(payload),
-      {
-        withCredentials: true,
-      },
-    );
+      const response = await axiosInstance.post<MinervaPlugin>(
+        apiPath.registerPluign(),
+        new URLSearchParams(payload),
+        {
+          withCredentials: true,
+        },
+      );
 
-    const isDataValid = validateDataUsingZodSchema(response.data, pluginSchema);
+      const isDataValid = validateDataUsingZodSchema(response.data, pluginSchema);
 
-    if (isDataValid) {
-      return response.data;
-    }
+      if (isDataValid) {
+        return response.data;
+      }
 
-    return undefined;
+      return undefined;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: PLUGIN_REGISTER_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
@@ -61,38 +71,49 @@ type GetInitPluginsProps = {
   }) => void;
 };
 
-export const getInitPlugins = createAsyncThunk<void, GetInitPluginsProps>(
+export const getInitPlugins = createAsyncThunk<void, GetInitPluginsProps, ThunkConfig>(
   'plugins/getInitPlugins',
-  async ({ pluginsId, setHashedPlugin }): Promise<void> => {
-    /* eslint-disable no-restricted-syntax, no-await-in-loop */
-    for (const pluginId of pluginsId) {
-      const res = await axiosInstance<MinervaPlugin>(apiPath.getPlugin(pluginId));
+  // eslint-disable-next-line consistent-return
+  async ({ pluginsId, setHashedPlugin }, { rejectWithValue }) => {
+    try {
+      /* eslint-disable no-restricted-syntax, no-await-in-loop */
+      for (const pluginId of pluginsId) {
+        const res = await axiosInstance<MinervaPlugin>(apiPath.getPlugin(pluginId));
 
-      const isDataValid = validateDataUsingZodSchema(res.data, pluginSchema);
+        const isDataValid = validateDataUsingZodSchema(res.data, pluginSchema);
 
-      if (isDataValid) {
-        const { urls } = res.data;
-        const scriptRes = await axios(urls[0]);
-        const pluginScript = scriptRes.data;
-        setHashedPlugin({ pluginUrl: urls[0], pluginScript });
+        if (isDataValid) {
+          const { urls } = res.data;
+          const scriptRes = await axios(urls[0]);
+          const pluginScript = scriptRes.data;
+          setHashedPlugin({ pluginUrl: urls[0], pluginScript });
 
-        /* eslint-disable no-new-func */
-        const loadPlugin = new Function(pluginScript);
-        loadPlugin();
+          /* eslint-disable no-new-func */
+          const loadPlugin = new Function(pluginScript);
+          loadPlugin();
+        }
       }
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: PLUGIN_INIT_FETCHING_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
     }
   },
 );
 
-export const getAllPlugins = createAsyncThunk(
+export const getAllPlugins = createAsyncThunk<MinervaPlugin[], void, ThunkConfig>(
   'plugins/getAllPlugins',
-  async (): Promise<MinervaPlugin[]> => {
-    const response = await axiosInstance.get<MinervaPlugin[]>(apiPath.getAllPlugins());
+  async (_, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstance.get<MinervaPlugin[]>(apiPath.getAllPlugins());
 
-    const isPluginDataValid = (pluginData: MinervaPlugin): boolean =>
-      validateDataUsingZodSchema(pluginData, pluginSchema);
-    const validPlugins = response.data.filter(isPluginDataValid);
+      const isPluginDataValid = (pluginData: MinervaPlugin): boolean =>
+        validateDataUsingZodSchema(pluginData, pluginSchema);
+      const validPlugins = response.data.filter(isPluginDataValid);
 
-    return validPlugins;
+      return validPlugins;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: PLUGIN_FETCHING_ALL_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/project/project.constants.ts b/src/redux/project/project.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..46757eb5187a0e2e6e8720aa67af4ee97dbb31b4
--- /dev/null
+++ b/src/redux/project/project.constants.ts
@@ -0,0 +1 @@
+export const PROJECT_FETCHING_ERROR_PREFIX = 'Failed to fetch project by id';
diff --git a/src/redux/project/project.reducers.test.ts b/src/redux/project/project.reducers.test.ts
index 744f725261ca8605d915b0da3474c3300526d24d..f3c007766b44ea26789d010ffccb631808e843c0 100644
--- a/src/redux/project/project.reducers.test.ts
+++ b/src/redux/project/project.reducers.test.ts
@@ -47,10 +47,13 @@ describe('project reducer', () => {
   it('should update store after failed getProjectById query', async () => {
     mockedAxiosClient.onGet(apiPath.getProjectById(PROJECT_ID)).reply(HttpStatusCode.NotFound, []);
 
-    const { type } = await store.dispatch(getProjectById(PROJECT_ID));
+    const { type, payload } = await store.dispatch(getProjectById(PROJECT_ID));
     const { data, loading, error } = store.getState().project;
 
     expect(type).toBe('project/getProjectById/rejected');
+    expect(payload).toBe(
+      "Failed to fetch project by id: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
     expect(loading).toEqual('failed');
     expect(error).toEqual({ message: '', name: '' });
     expect(data).toEqual(undefined);
diff --git a/src/redux/project/project.thunks.ts b/src/redux/project/project.thunks.ts
index 649f867d87cf8581543559dc5f2c2a2911ea3388..2ef8de8212f136df6f1a6810bea8e0ebf31806bc 100644
--- a/src/redux/project/project.thunks.ts
+++ b/src/redux/project/project.thunks.ts
@@ -3,15 +3,23 @@ import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { Project } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import { apiPath } from '../apiPath';
+import { PROJECT_FETCHING_ERROR_PREFIX } from './project.constants';
 
-export const getProjectById = createAsyncThunk(
+export const getProjectById = createAsyncThunk<Project | undefined, string, ThunkConfig>(
   'project/getProjectById',
-  async (id: string): Promise<Project | undefined> => {
-    const response = await axiosInstanceNewAPI.get<Project>(apiPath.getProjectById(id));
+  async (id, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstanceNewAPI.get<Project>(apiPath.getProjectById(id));
 
-    const isDataValid = validateDataUsingZodSchema(response.data, projectSchema);
+      const isDataValid = validateDataUsingZodSchema(response.data, projectSchema);
 
-    return isDataValid ? response.data : undefined;
+      return isDataValid ? response.data : undefined;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: PROJECT_FETCHING_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/publications/publications.constatns.ts b/src/redux/publications/publications.constatns.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2f5ea0a3dfe3f353ad71316f677d88888b68fd2a
--- /dev/null
+++ b/src/redux/publications/publications.constatns.ts
@@ -0,0 +1 @@
+export const PUBLICATIONS_FETCHING_ERROR_PREFIX = 'Problem with fetching publications';
diff --git a/src/redux/publications/publications.thunks.ts b/src/redux/publications/publications.thunks.ts
index e95a1d06a07c05963b29f22e740bab6e1e264ad4..f50b611eec013b7e09a0b9773775f6fafc9e4cba 100644
--- a/src/redux/publications/publications.thunks.ts
+++ b/src/redux/publications/publications.thunks.ts
@@ -3,16 +3,25 @@ import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { axiosInstance } from '@/services/api/utils/axiosInstance';
 import { PublicationsResponse } from '@/types/models';
 import { publicationsResponseSchema } from '@/models/publicationsResponseSchema';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import { GetPublicationsParams } from './publications.types';
 import { apiPath } from '../apiPath';
+import { PUBLICATIONS_FETCHING_ERROR_PREFIX } from './publications.constatns';
 
-export const getPublications = createAsyncThunk(
-  'publications/getPublications',
-  async (params: GetPublicationsParams): Promise<PublicationsResponse | undefined> => {
+export const getPublications = createAsyncThunk<
+  PublicationsResponse | undefined,
+  GetPublicationsParams,
+  ThunkConfig
+>('publications/getPublications', async (params, { rejectWithValue }) => {
+  try {
     const response = await axiosInstance.get<PublicationsResponse>(apiPath.getPublications(params));
 
     const isDataValid = validateDataUsingZodSchema(response.data, publicationsResponseSchema);
 
     return isDataValid ? response.data : undefined;
-  },
-);
+  } catch (error) {
+    const errorMessage = getErrorMessage({ error, prefix: PUBLICATIONS_FETCHING_ERROR_PREFIX });
+    return rejectWithValue(errorMessage);
+  }
+});
diff --git a/src/redux/reactions/reactions.constants.ts b/src/redux/reactions/reactions.constants.ts
index a7b9f099193540abc66d052d902faee2d5775c76..c5f51f9d4bfb67f52a7e543eb115c69bcec43eef 100644
--- a/src/redux/reactions/reactions.constants.ts
+++ b/src/redux/reactions/reactions.constants.ts
@@ -5,3 +5,5 @@ export const REACTIONS_INITIAL_STATE: ReactionsState = {
   loading: 'idle',
   error: { name: '', message: '' },
 };
+
+export const REACTIONS_FETCHING_ERROR_PREFIX = 'Failed to fetch reactions';
diff --git a/src/redux/reactions/reactions.thunks.ts b/src/redux/reactions/reactions.thunks.ts
index dbbf7fc725b6501dc9f4136705df1ae56b539ba4..fde44e5d8436d162a53b1b76e0eb0fb09b0753fb 100644
--- a/src/redux/reactions/reactions.thunks.ts
+++ b/src/redux/reactions/reactions.thunks.ts
@@ -2,20 +2,28 @@ import { reactionSchema } from '@/models/reaction';
 import { apiPath } from '@/redux/apiPath';
 import { axiosInstance } from '@/services/api/utils/axiosInstance';
 import { Reaction } from '@/types/models';
+import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { ThunkConfig } from '@/types/store';
+import { REACTIONS_FETCHING_ERROR_PREFIX } from './reactions.constants';
 
-export const getReactionsByIds = createAsyncThunk<Reaction[] | undefined, number[]>(
+export const getReactionsByIds = createAsyncThunk<Reaction[] | undefined, number[], ThunkConfig>(
   'reactions/getByIds',
-  async (ids: number[]): Promise<Reaction[] | undefined> => {
-    const response = await axiosInstance.get<Reaction[]>(apiPath.getReactionsWithIds(ids));
-    const isDataValid = validateDataUsingZodSchema(response.data, z.array(reactionSchema));
+  async (ids, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstance.get<Reaction[]>(apiPath.getReactionsWithIds(ids));
+      const isDataValid = validateDataUsingZodSchema(response.data, z.array(reactionSchema));
 
-    if (!isDataValid) {
-      return undefined;
-    }
+      if (!isDataValid) {
+        return undefined;
+      }
 
-    return response.data;
+      return response.data;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: REACTIONS_FETCHING_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/search/search.constants.ts b/src/redux/search/search.constants.ts
index 962778465db9e927729e9369e826702d72b1a166..5c13f6fd0e196fd7b0a3119983d6dd229a77c072 100644
--- a/src/redux/search/search.constants.ts
+++ b/src/redux/search/search.constants.ts
@@ -5,3 +5,5 @@ export const SEARCH_INITIAL_STATE: SearchState = {
   perfectMatch: false,
   loading: 'idle',
 };
+
+export const DATA_SEARCHING_ERROR_PREFIX = 'Failed to search data';
diff --git a/src/redux/search/search.thunks.ts b/src/redux/search/search.thunks.ts
index 05debcd0c57d9a3adc4872ef02b7bb5d876c8e0f..078947d3586dc7be7319db5b4196992779539f2d 100644
--- a/src/redux/search/search.thunks.ts
+++ b/src/redux/search/search.thunks.ts
@@ -3,20 +3,34 @@ import { getMultiChemicals } from '@/redux/chemicals/chemicals.thunks';
 import { getMultiDrugs } from '@/redux/drugs/drugs.thunks';
 import { PerfectMultiSearchParams } from '@/types/search';
 import { createAsyncThunk } from '@reduxjs/toolkit';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import type { RootState } from '../store';
 import { dispatchPluginsEvents } from './search.thunks.utils';
+import { DATA_SEARCHING_ERROR_PREFIX } from './search.constants';
 
 type GetSearchDataProps = PerfectMultiSearchParams;
 
-export const getSearchData = createAsyncThunk<void, GetSearchDataProps, { state: RootState }>(
+export const getSearchData = createAsyncThunk<
+  void,
+  GetSearchDataProps,
+  { state: RootState } & ThunkConfig
+>(
   'project/getSearchData',
-  async ({ searchQueries, isPerfectMatch }, { dispatch, getState }): Promise<void> => {
-    await Promise.all([
-      dispatch(getMultiBioEntity({ searchQueries, isPerfectMatch })),
-      dispatch(getMultiDrugs(searchQueries)),
-      dispatch(getMultiChemicals(searchQueries)),
-    ]);
+  // eslint-disable-next-line consistent-return
+  async ({ searchQueries, isPerfectMatch }, { dispatch, getState, rejectWithValue }) => {
+    try {
+      await Promise.all([
+        dispatch(getMultiBioEntity({ searchQueries, isPerfectMatch })),
+        dispatch(getMultiDrugs(searchQueries)),
+        dispatch(getMultiChemicals(searchQueries)),
+      ]);
 
-    dispatchPluginsEvents(searchQueries, getState());
+      dispatchPluginsEvents(searchQueries, getState());
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: DATA_SEARCHING_ERROR_PREFIX });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/statistics/statistics.constants.ts b/src/redux/statistics/statistics.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8b28b57b0cd8e505631ebdc0a2e16d003cea8544
--- /dev/null
+++ b/src/redux/statistics/statistics.constants.ts
@@ -0,0 +1 @@
+export const STATISTICS_FETCHING_ERROR_PREFIX = 'Failed to fetch statistics';
diff --git a/src/redux/statistics/statistics.reducers.test.ts b/src/redux/statistics/statistics.reducers.test.ts
index af16b53be20193600a546122f08bba5e3d6f9b85..6d620db1720db9fa9f929ed84fe94c1cb32d8b0c 100644
--- a/src/redux/statistics/statistics.reducers.test.ts
+++ b/src/redux/statistics/statistics.reducers.test.ts
@@ -56,10 +56,13 @@ describe('statistics reducer', () => {
       .onGet(apiPath.getStatisticsById(PROJECT_ID))
       .reply(HttpStatusCode.NotFound, undefined);
 
-    const { type } = await store.dispatch(getStatisticsById(PROJECT_ID));
+    const { type, payload } = await store.dispatch(getStatisticsById(PROJECT_ID));
     const { loading } = store.getState().statistics;
 
     expect(type).toBe('statistics/getStatisticsById/rejected');
+    expect(payload).toBe(
+      "Failed to fetch statistics: The page you're looking for doesn't exist. Please verify the URL and try again.",
+    );
 
     waitFor(() => {
       expect(loading).toEqual('pending');
diff --git a/src/redux/statistics/statistics.thunks.ts b/src/redux/statistics/statistics.thunks.ts
index df5b6589b37a03472c231a24a0ea8fa4b0b7bbd2..1a683a4e3ea3e50238f1fce85b47dbde93b59b98 100644
--- a/src/redux/statistics/statistics.thunks.ts
+++ b/src/redux/statistics/statistics.thunks.ts
@@ -3,15 +3,23 @@ import { Statistics } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { statisticsSchema } from '@/models/statisticsSchema';
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { ThunkConfig } from '@/types/store';
 import { apiPath } from '../apiPath';
+import { STATISTICS_FETCHING_ERROR_PREFIX } from './statistics.constants';
 
-export const getStatisticsById = createAsyncThunk(
+export const getStatisticsById = createAsyncThunk<Statistics | undefined, string, ThunkConfig>(
   'statistics/getStatisticsById',
-  async (id: string): Promise<Statistics | undefined> => {
-    const response = await axiosInstance.get<Statistics>(apiPath.getStatisticsById(id));
+  async (id, { rejectWithValue }) => {
+    try {
+      const response = await axiosInstance.get<Statistics>(apiPath.getStatisticsById(id));
 
-    const isDataValid = validateDataUsingZodSchema(response.data, statisticsSchema);
+      const isDataValid = validateDataUsingZodSchema(response.data, statisticsSchema);
 
-    return isDataValid ? response.data : undefined;
+      return isDataValid ? response.data : undefined;
+    } catch (error) {
+      const errorMessage = getErrorMessage({ error, prefix: STATISTICS_FETCHING_ERROR_PREFIX });
+      return rejectWithValue(errorMessage);
+    }
   },
 );
diff --git a/src/redux/store.ts b/src/redux/store.ts
index 2391ea22a323314c9cb853939d9492a6d036e924..3fb15d8bb7a91d5e21285b67ba6fcf586ae93a2b 100644
--- a/src/redux/store.ts
+++ b/src/redux/store.ts
@@ -29,6 +29,7 @@ import { mapListenerMiddleware } from './map/middleware/map.middleware';
 import markersReducer from './markers/markers.slice';
 import pluginsReducer from './plugins/plugins.slice';
 import publicationsReducer from './publications/publications.slice';
+import { errorListenerMiddleware } from './middlewares/error.middleware';
 import statisticsReducer from './statistics/statistics.slice';
 
 export const reducers = {
@@ -58,7 +59,7 @@ export const reducers = {
   markers: markersReducer,
 };
 
-export const middlewares = [mapListenerMiddleware.middleware];
+export const middlewares = [mapListenerMiddleware.middleware, errorListenerMiddleware.middleware];
 
 export const store = configureStore({
   reducer: reducers,
diff --git a/src/redux/user/user.thunks.ts b/src/redux/user/user.thunks.ts
index 95c567c2af83b31f62eb05c30d219f6f17bdb6af..e6241bb6f2ecad36de3b16f7f73146951c40dc8b 100644
--- a/src/redux/user/user.thunks.ts
+++ b/src/redux/user/user.thunks.ts
@@ -4,21 +4,31 @@ import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { loginSchema } from '@/models/loginSchema';
 import { sessionSchemaValid } from '@/models/sessionValidSchema';
 import { Login, SessionValid } from '@/types/models';
+import { getErrorMessage } from '@/utils/getErrorMessage';
 import { apiPath } from '../apiPath';
 import { closeModal } from '../modal/modal.slice';
 
 export const login = createAsyncThunk(
   'user/login',
-  async (credentials: { login: string; password: string }, { dispatch }) => {
-    const searchParams = new URLSearchParams(credentials);
-    const response = await axiosInstance.post<Login>(apiPath.postLogin(), searchParams, {
-      withCredentials: true,
-    });
+  async (credentials: { login: string; password: string }, { dispatch, rejectWithValue }) => {
+    try {
+      const searchParams = new URLSearchParams(credentials);
+      const response = await axiosInstance.post<Login>(apiPath.postLogin(), searchParams, {
+        withCredentials: true,
+      });
 
-    const isDataValid = validateDataUsingZodSchema(response.data, loginSchema);
-    dispatch(closeModal());
+      const isDataValid = validateDataUsingZodSchema(response.data, loginSchema);
+      dispatch(closeModal());
 
-    return isDataValid ? response.data : undefined;
+      return isDataValid ? response.data : undefined;
+    } catch (error) {
+      const errorMessage = getErrorMessage({
+        error,
+        prefix: 'Login',
+      });
+
+      return rejectWithValue(errorMessage);
+    }
   },
 );
 
diff --git a/src/services/pluginsManager/map/triggerSearch/searchByQuery.ts b/src/services/pluginsManager/map/triggerSearch/searchByQuery.ts
index 4f48c0a74b0ad1067c66bc99dfd539b0001a695d..e29c50f97532b73a77fe158f1d4e2571ff58bb4b 100644
--- a/src/services/pluginsManager/map/triggerSearch/searchByQuery.ts
+++ b/src/services/pluginsManager/map/triggerSearch/searchByQuery.ts
@@ -19,9 +19,6 @@ export const searchByQuery = (
       if (hasFitBounds) {
         searchFitBounds();
       }
-    })
-    .catch(() => {
-      // TODO to discuss manage state of failure
     });
 
   displaySearchDrawerWithSelectedDefaultTab(searchValues);
diff --git a/src/shared/Toast/Toast.component.test.tsx b/src/shared/Toast/Toast.component.test.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..610df96f168afee935ae509c76a42019302a38c9
--- /dev/null
+++ b/src/shared/Toast/Toast.component.test.tsx
@@ -0,0 +1,29 @@
+/* eslint-disable no-magic-numbers */
+import { render, screen, fireEvent } from '@testing-library/react';
+import { Toast } from './Toast.component';
+
+describe('Toast component', () => {
+  it('renders success message correctly', () => {
+    const message = 'Success message';
+    render(<Toast type="success" message={message} onDismiss={() => {}} />);
+    const toastElement = screen.getByText(message);
+    expect(toastElement).toBeInTheDocument();
+    expect(toastElement).toHaveClass('text-green-500');
+  });
+
+  it('renders error message correctly', () => {
+    const message = 'Error message';
+    render(<Toast type="error" message={message} onDismiss={() => {}} />);
+    const toastElement = screen.getByText(message);
+    expect(toastElement).toBeInTheDocument();
+    expect(toastElement).toHaveClass('text-red-500');
+  });
+
+  it('calls onDismiss when close button is clicked', () => {
+    const mockOnDismiss = jest.fn();
+    render(<Toast type="success" message="Success message" onDismiss={mockOnDismiss} />);
+    const closeButton = screen.getByRole('button');
+    fireEvent.click(closeButton);
+    expect(mockOnDismiss).toHaveBeenCalledTimes(1);
+  });
+});
diff --git a/src/shared/Toast/Toast.component.tsx b/src/shared/Toast/Toast.component.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..02e1d965aa9bfc79143337d7ac11254cc6059f8c
--- /dev/null
+++ b/src/shared/Toast/Toast.component.tsx
@@ -0,0 +1,30 @@
+import { twMerge } from 'tailwind-merge';
+import { Icon } from '../Icon';
+
+type ToastArgs = {
+  type: 'success' | 'error';
+  message: string;
+  onDismiss: () => void;
+};
+
+export const Toast = ({ type, message, onDismiss }: ToastArgs): React.ReactNode => (
+  <div
+    className={twMerge(
+      'flex h-[76px] w-[700px] items-center rounded-l rounded-r-lg bg-white p-4 drop-shadow before:absolute before:inset-y-0 before:left-0 before:block before:w-1 before:rounded-l-lg before:content-[""]',
+      type === 'error' ? 'before:bg-red-500' : 'before:bg-green-500',
+    )}
+  >
+    <p
+      className={twMerge(
+        'text-base font-bold ',
+        type === 'error' ? 'text-red-500' : 'text-green-500',
+      )}
+    >
+      {message}
+    </p>
+
+    <button type="button" onClick={onDismiss} className="ml-auto flex-none">
+      <Icon name="close" className="ml-3 h-7 w-7 fill-font-500" />
+    </button>
+  </div>
+);
diff --git a/src/shared/Toast/index.ts b/src/shared/Toast/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c28ae1894e90798a5f9852ee719937588b8b0814
--- /dev/null
+++ b/src/shared/Toast/index.ts
@@ -0,0 +1 @@
+export { Toast } from './Toast.component';
diff --git a/src/types/store.ts b/src/types/store.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c513f8db4485126f755cd2fa6346e55f126f8fa1
--- /dev/null
+++ b/src/types/store.ts
@@ -0,0 +1,3 @@
+export type ThunkConfig = {
+  rejectValue: string;
+};
diff --git a/src/utils/getErrorMessage/getErrorMessage.constants.ts b/src/utils/getErrorMessage/getErrorMessage.constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..00b84d7087cf177ecf1a129633867153ce228e48
--- /dev/null
+++ b/src/utils/getErrorMessage/getErrorMessage.constants.ts
@@ -0,0 +1,11 @@
+export const UNKNOWN_ERROR = 'An unknown error occurred. Please try again later.';
+
+export const HTTP_ERROR_MESSAGES = {
+  400: "The server couldn't understand your request. Please check your input and try again.",
+  401: "You're not authorized to access this resource. Please log in or check your credentials.",
+  403: "Access Forbidden! You don't have permission to access this resource.",
+  404: "The page you're looking for doesn't exist. Please verify the URL and try again.",
+  500: 'Unexpected server error. Please try again later or contact support.',
+  501: 'Sorry, this feature is not yet implemented. Please try again later.',
+  503: 'Service Unavailable! The server is currently down for maintenance. Please try again later.',
+};
diff --git a/src/utils/getErrorMessage/getErrorMessage.test.ts b/src/utils/getErrorMessage/getErrorMessage.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2f9f2b7cd101c4ea2dccfcf5643190f1b9b25cf2
--- /dev/null
+++ b/src/utils/getErrorMessage/getErrorMessage.test.ts
@@ -0,0 +1,34 @@
+/* eslint-disable no-magic-numbers */
+import { getErrorMessage } from './getErrorMessage';
+import { mockAxiosError } from './getErrorMessage.test.utils';
+
+describe('getErrorMessage function', () => {
+  it('should return custom message if provided', () => {
+    const error = new Error('Custom Error');
+    const errorMessage = getErrorMessage({ error, message: 'This is a custom message' });
+    expect(errorMessage).toBe('This is a custom message');
+  });
+
+  it('should return extracted Axios error message', () => {
+    const error = mockAxiosError(401, 'Unauthorized');
+    const errorMessage = getErrorMessage({ error });
+    expect(errorMessage).toBe('Unauthorized');
+  });
+
+  it('should return error message from Error instance', () => {
+    const error = new Error('Network Error');
+    const errorMessage = getErrorMessage({ error });
+    expect(errorMessage).toBe('Network Error');
+  });
+
+  it('should return default error message if error is of unknown type', () => {
+    const errorMessage = getErrorMessage({ error: {} });
+    expect(errorMessage).toBe('An unknown error occurred. Please try again later.');
+  });
+
+  it('should prepend prefix to error message', () => {
+    const error = new Error('Server Error');
+    const errorMessage = getErrorMessage({ error, prefix: 'Error occurred' });
+    expect(errorMessage).toBe('Error occurred: Server Error');
+  });
+});
diff --git a/src/utils/getErrorMessage/getErrorMessage.test.utils.ts b/src/utils/getErrorMessage/getErrorMessage.test.utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb7983e53d39dbb032410d196c3ab37345042e48
--- /dev/null
+++ b/src/utils/getErrorMessage/getErrorMessage.test.utils.ts
@@ -0,0 +1,15 @@
+import { AxiosError } from 'axios';
+
+type MockAxiosError = AxiosError<{ error: string; reason: string }>;
+
+export const mockAxiosError = (status: number, reason: string | null): MockAxiosError =>
+  ({
+    isAxiosError: true,
+    response: {
+      status,
+      data: {
+        reason,
+        error: reason,
+      },
+    },
+  }) as MockAxiosError;
diff --git a/src/utils/getErrorMessage/getErrorMessage.ts b/src/utils/getErrorMessage/getErrorMessage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..20073f02e7d75ea19cbcbe1e4e8573031f25588f
--- /dev/null
+++ b/src/utils/getErrorMessage/getErrorMessage.ts
@@ -0,0 +1,29 @@
+import axios from 'axios';
+import { UNKNOWN_ERROR } from './getErrorMessage.constants';
+import { extractAxiosErrorMessage } from './getErrorMessage.utils';
+
+type GetErrorMessageConfig = {
+  error: unknown;
+  message?: string;
+  prefix?: string;
+};
+
+export const getErrorMessage = ({ error, message, prefix }: GetErrorMessageConfig): string => {
+  let errorMessage: string;
+
+  switch (true) {
+    case !!message:
+      errorMessage = message;
+      break;
+    case axios.isAxiosError(error):
+      errorMessage = extractAxiosErrorMessage(error);
+      break;
+    case error instanceof Error:
+      errorMessage = error.message;
+      break;
+    default:
+      errorMessage = UNKNOWN_ERROR;
+  }
+
+  return prefix ? `${prefix}: ${errorMessage}` : errorMessage;
+};
diff --git a/src/utils/getErrorMessage/getErrorMessage.types.ts b/src/utils/getErrorMessage/getErrorMessage.types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..33e843551e3bafc782ab11cc537a5565c9d5242d
--- /dev/null
+++ b/src/utils/getErrorMessage/getErrorMessage.types.ts
@@ -0,0 +1,3 @@
+import { HTTP_ERROR_MESSAGES } from './getErrorMessage.constants';
+
+export type HttpStatuses = keyof typeof HTTP_ERROR_MESSAGES;
diff --git a/src/utils/getErrorMessage/getErrorMessage.utils.test.ts b/src/utils/getErrorMessage/getErrorMessage.utils.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8406dcaf7f0d7751d6c85d3d7e92b2028495e30c
--- /dev/null
+++ b/src/utils/getErrorMessage/getErrorMessage.utils.test.ts
@@ -0,0 +1,22 @@
+/* eslint-disable no-magic-numbers */
+import { mockAxiosError } from './getErrorMessage.test.utils';
+import { extractAxiosErrorMessage } from './getErrorMessage.utils';
+
+describe('extractAxiosErrorMessage', () => {
+  it('should return the error message from Axios error response if exist', () => {
+    const error = mockAxiosError(404, 'Not Found');
+    expect(extractAxiosErrorMessage(error)).toBe('Not Found');
+  });
+  it('should return error message defined by response status if error response does not exist', () => {
+    const error = mockAxiosError(500, null);
+    expect(extractAxiosErrorMessage(error)).toBe(
+      'Unexpected server error. Please try again later or contact support.',
+    );
+  });
+  it('should return the default error message if status code is not defined in predefined error messages list and error response does not exist', () => {
+    const error = mockAxiosError(418, null);
+    expect(extractAxiosErrorMessage(error)).toBe(
+      'An unknown error occurred. Please try again later.',
+    );
+  });
+});
diff --git a/src/utils/getErrorMessage/getErrorMessage.utils.ts b/src/utils/getErrorMessage/getErrorMessage.utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..46a46ee43c3c8b694a5100c4d3300c42d9a39e29
--- /dev/null
+++ b/src/utils/getErrorMessage/getErrorMessage.utils.ts
@@ -0,0 +1,14 @@
+import { AxiosError } from 'axios';
+import { HTTP_ERROR_MESSAGES, UNKNOWN_ERROR } from './getErrorMessage.constants';
+import { HttpStatuses } from './getErrorMessage.types';
+
+type Error = { error: string; reason: string };
+
+export const extractAxiosErrorMessage = (error: AxiosError<Error>): string => {
+  if (error.response?.data?.reason) {
+    return error.response.data.reason;
+  }
+
+  const status = error.response?.status as HttpStatuses;
+  return HTTP_ERROR_MESSAGES[status] || UNKNOWN_ERROR;
+};
diff --git a/src/utils/getErrorMessage/index.ts b/src/utils/getErrorMessage/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..50ca645d9391ddb5593acfcd24d296412d18a731
--- /dev/null
+++ b/src/utils/getErrorMessage/index.ts
@@ -0,0 +1 @@
+export { getErrorMessage } from './getErrorMessage';
diff --git a/src/utils/showToast.test.tsx b/src/utils/showToast.test.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..01f65adebfafe68142553d337ef699c66b9a75b5
--- /dev/null
+++ b/src/utils/showToast.test.tsx
@@ -0,0 +1,21 @@
+/* eslint-disable no-magic-numbers */
+import { toast } from 'sonner';
+import { showToast } from './showToast';
+
+jest.mock('sonner', () => ({
+  toast: {
+    custom: jest.fn(),
+    dismiss: jest.fn(),
+  },
+}));
+
+describe('showToast', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should call toast.custom on showToast call', () => {
+    showToast({ type: 'success', message: 'Success message' });
+    expect(toast.custom).toHaveBeenCalledTimes(1);
+  });
+});
diff --git a/src/utils/showToast.tsx b/src/utils/showToast.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..c7ea4329137a508aec4b93357e63442ef6c3c795
--- /dev/null
+++ b/src/utils/showToast.tsx
@@ -0,0 +1,13 @@
+import { toast } from 'sonner';
+import { Toast } from '@/shared/Toast';
+
+type ShowToastArgs = {
+  type: 'success' | 'error';
+  message: string;
+};
+
+export const showToast = (args: ShowToastArgs): void => {
+  toast.custom(t => (
+    <Toast message={args.message} onDismiss={() => toast.dismiss(t)} type={args.type} />
+  ));
+};