diff --git a/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx b/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
index aaf74bf636298beca86281a2d6c9cb9e657eecb4..b8015a4bda66ceedeb92c00b3c2f3276d48bb871 100644
--- a/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
@@ -46,6 +46,7 @@ describe('EditOverlayModal - component', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
     });
 
@@ -63,6 +64,7 @@ describe('EditOverlayModal - component', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
     });
 
@@ -83,6 +85,7 @@ describe('EditOverlayModal - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -91,6 +94,7 @@ describe('EditOverlayModal - component', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -116,6 +120,7 @@ describe('EditOverlayModal - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -124,6 +129,7 @@ describe('EditOverlayModal - component', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -150,6 +156,7 @@ describe('EditOverlayModal - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -158,6 +165,7 @@ describe('EditOverlayModal - component', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -183,6 +191,7 @@ describe('EditOverlayModal - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -191,6 +200,7 @@ describe('EditOverlayModal - component', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -219,6 +229,7 @@ describe('EditOverlayModal - component', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
     });
 
diff --git a/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts b/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts
index 8109120a0830f36538a1e86e4b83459f43c3a0dc..172a10260690e968f93774434a5223a1d57c0ccc 100644
--- a/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts
+++ b/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts
@@ -14,6 +14,7 @@ describe('useEditOverlay', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -22,6 +23,7 @@ describe('useEditOverlay', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
     });
 
@@ -48,6 +50,7 @@ describe('useEditOverlay', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -56,6 +59,7 @@ describe('useEditOverlay', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
     });
 
@@ -85,6 +89,7 @@ describe('useEditOverlay', () => {
         error: DEFAULT_ERROR,
         login: null,
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -93,6 +98,7 @@ describe('useEditOverlay', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
     });
 
@@ -118,6 +124,7 @@ describe('useEditOverlay', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -126,6 +133,7 @@ describe('useEditOverlay', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
     });
 
@@ -152,6 +160,7 @@ describe('useEditOverlay', () => {
         error: DEFAULT_ERROR,
         login: null,
         role: 'user',
+        userData: null,
       },
       modal: {
         isOpen: true,
@@ -160,6 +169,7 @@ describe('useEditOverlay', () => {
         editOverlayState: overlayFixture,
         molArtState: {},
         overviewImagesState: {},
+        errorReportState: {},
       },
     });
 
diff --git a/src/components/FunctionalArea/Modal/ErrorReportModal/ErroReportModal.component.tsx b/src/components/FunctionalArea/Modal/ErrorReportModal/ErroReportModal.component.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..bfc5c1bb1d40793ea528fb920f882e3a2976f2dc
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/ErrorReportModal/ErroReportModal.component.tsx
@@ -0,0 +1,170 @@
+/* eslint-disable jsx-a11y/label-has-associated-control */
+import { useAppSelector } from '@/redux/hooks/useAppSelector';
+import { Button } from '@/shared/Button';
+import { Input } from '@/shared/Input';
+import React from 'react';
+import { currentErrorDataSelector } from '@/redux/modal/modal.selector';
+import { sendReport } from '@/utils/error-report/sendErrorReport';
+import { ONE_THOUSAND } from '@/constants/common';
+import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
+import { closeModal } from '@/redux/modal/modal.slice';
+
+export const ErrorReportModal: React.FC = () => {
+  const dispatch = useAppDispatch();
+  const errorData = useAppSelector(currentErrorDataSelector);
+
+  function getValue(nullableVale: string | null | undefined): string {
+    if (!nullableVale) {
+      return '';
+    }
+    return nullableVale;
+  }
+
+  const url = getValue(errorData?.url);
+  const browser = getValue(errorData?.browser);
+  const comment = getValue(errorData?.comment);
+  const login = getValue(errorData?.login);
+  const email = getValue(errorData?.email);
+  const javaStacktrace = getValue(errorData?.javaStacktrace);
+  const stacktrace = getValue(errorData?.stacktrace);
+  const version = getValue(errorData?.version);
+  const message = getValue(errorData?.message);
+  const timestamp = errorData ? errorData.timestamp : Math.floor(+new Date() / ONE_THOUSAND);
+
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  const [errorDataToSend, setValue] = React.useState({
+    url,
+    browser,
+    comment,
+    login,
+    email,
+    javaStacktrace,
+    stacktrace,
+    version,
+    timestamp,
+    message,
+  });
+
+  const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
+    const { name, checked } = e.target;
+    let { value } = e.target;
+    setValue(errorData2 => {
+      if (name === 'login') {
+        const loginValue = checked ? login : '';
+        const emailValue = checked ? email : '';
+
+        return { ...errorData2, login: loginValue, email: emailValue };
+      }
+      if (name === 'url') {
+        value = checked ? url : '';
+      }
+      if (name === 'browser') {
+        value = checked ? browser : '';
+      }
+      if (name === 'version') {
+        value = checked ? version : '';
+      }
+      return { ...errorData2, [name]: value };
+    });
+  };
+
+  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>): Promise<void> => {
+    e.preventDefault();
+    await dispatch(sendReport(errorDataToSend));
+    dispatch(closeModal());
+  };
+
+  return (
+    <div className="w-[800px] border border-t-[#E1E0E6] bg-white">
+      <form onSubmit={handleSubmit} className="p-4">
+        <p className="my-4 font-bold"> {errorDataToSend.message}</p>
+        <p className="my-4">
+          If you agree to submit the following information to the minerva maintainers please uncheck
+          all boxes that might contain sensitive data.
+        </p>
+        <label className="mb-1 mt-4 block text-sm" htmlFor="comment">
+          <span className="font-semibold">Add comment</span> (max 1000 characters):
+        </label>
+        <Input
+          type="textarea"
+          name="comment"
+          id="comment"
+          onChange={handleChange}
+          value={errorDataToSend.comment}
+          className="mb-4 text-sm font-medium text-font-400"
+        />
+        <div className="grid grid-cols-[15px_743px] gap-2">
+          <label className="flex-1 text-sm font-semibold" htmlFor="url">
+            <Input
+              styleVariant="primaryWithoutFull"
+              id="url"
+              name="url"
+              type="checkbox"
+              onChange={handleChange}
+              checked={errorDataToSend.url !== ''}
+              className="flex-1 align-bottom text-sm font-semibold"
+            />
+          </label>
+          <label className="block border border-transparent bg-cultured px-2 py-2.5 text-sm font-medium outline-none hover:border-greyscale-600 focus:border-greyscale-600">
+            {url}
+          </label>
+          <label className="block text-sm font-semibold">
+            <Input
+              styleVariant="primaryWithoutFull"
+              id="browser"
+              name="browser"
+              type="checkbox"
+              onChange={handleChange}
+              checked={errorDataToSend.browser !== ''}
+              className="flex-1 align-bottom text-sm font-semibold"
+            />
+          </label>
+          <label className="block border border-transparent bg-cultured px-2 py-2.5 text-sm font-medium outline-none hover:border-greyscale-600 focus:border-greyscale-600">
+            {browser}
+          </label>
+          <label className="block text-sm font-semibold">
+            <Input
+              id="login"
+              name="login"
+              type="checkbox"
+              onChange={handleChange}
+              checked={errorDataToSend.login !== ''}
+              styleVariant="primaryWithoutFull"
+              className="flex-1 align-bottom text-sm font-semibold"
+            />
+          </label>
+          <label className="block border border-transparent bg-cultured px-2 py-2.5 text-sm font-medium outline-none hover:border-greyscale-600 focus:border-greyscale-600">
+            {login} (email: {email})
+          </label>
+          <label className="block text-sm font-semibold">
+            <Input
+              styleVariant="primaryWithoutFull"
+              id="version"
+              name="version"
+              type="checkbox"
+              onChange={handleChange}
+              checked={errorDataToSend.version !== ''}
+              className="flex-1 align-bottom text-sm font-semibold"
+            />
+          </label>
+          <label className="block border border-transparent bg-cultured px-2 py-2.5 text-sm font-medium outline-none hover:border-greyscale-600 focus:border-greyscale-600">
+            Minerva {version}
+          </label>
+        </div>
+
+        <div className="my-4 block max-h-20 overflow-auto border border-transparent bg-cultured px-2 py-2.5 text-sm font-medium outline-none hover:border-greyscale-600 focus:border-greyscale-600">
+          Stacktrace:
+          <pre>{errorDataToSend.stacktrace}</pre>
+        </div>
+        <div className="my-4 block max-h-20 overflow-auto border border-transparent bg-cultured px-2 py-2.5 text-sm font-medium outline-none hover:border-greyscale-600 focus:border-greyscale-600">
+          Backend stacktrace:
+          <pre>{errorDataToSend.javaStacktrace}</pre>
+        </div>
+
+        <Button type="submit" className="w-full justify-center text-base font-medium">
+          Submit
+        </Button>
+      </form>
+    </div>
+  );
+};
diff --git a/src/components/FunctionalArea/Modal/ErrorReportModal/index.ts b/src/components/FunctionalArea/Modal/ErrorReportModal/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..016741c087dae51bd3f16b61b5acfc5d07ef564d
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/ErrorReportModal/index.ts
@@ -0,0 +1 @@
+export { ErrorReportModal } from './ErroReportModal.component';
diff --git a/src/components/FunctionalArea/Modal/LoginModal/LoginModal.component.test.tsx b/src/components/FunctionalArea/Modal/LoginModal/LoginModal.component.test.tsx
index ca8aef6cc2e75352bf0538dce2681bf63a7bb06a..3887053892dda1e0ff1344fbb2705fb8662cf58b 100644
--- a/src/components/FunctionalArea/Modal/LoginModal/LoginModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LoginModal/LoginModal.component.test.tsx
@@ -10,8 +10,8 @@ import { apiPath } from '@/redux/apiPath';
 import { HttpStatusCode } from 'axios';
 import { loginFixture } from '@/models/fixtures/loginFixture';
 import { overlaysFixture } from '@/models/fixtures/overlaysFixture';
-import { userPrivilegesFixture } from '@/models/fixtures/userPrivilegesFixture';
 import { MODAL_INITIAL_STATE_MOCK } from '@/redux/modal/modal.mock';
+import { userFixture } from '@/models/fixtures/userFixture';
 import { LoginModal } from './LoginModal.component';
 
 const mockedAxiosClient = mockNetworkResponse();
@@ -71,9 +71,7 @@ describe('LoginModal - component', () => {
   });
   it('should fetch user overlays when login is successful', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient
-      .onGet(apiPath.userPrivileges(loginFixture.login))
-      .reply(HttpStatusCode.Ok, userPrivilegesFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
     mockedAxiosClient
       .onGet(
         apiPath.getAllUserOverlaysByCreatorQuery({
@@ -103,8 +101,8 @@ describe('LoginModal - component', () => {
   });
   it('should display loggedInMenuModal after successful login as admin', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient.onGet(apiPath.userPrivileges(loginFixture.login)).reply(HttpStatusCode.Ok, {
-      ...userPrivilegesFixture,
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, {
+      ...userFixture,
       privileges: [
         {
           privilegeType: 'IS_ADMIN',
@@ -142,8 +140,8 @@ describe('LoginModal - component', () => {
   });
   it('should display loggedInMenuModal after successful login as curator', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient.onGet(apiPath.userPrivileges(loginFixture.login)).reply(HttpStatusCode.Ok, {
-      ...userPrivilegesFixture,
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, {
+      ...userFixture,
       privileges: [
         {
           privilegeType: 'IS_CURATOR',
@@ -181,9 +179,7 @@ describe('LoginModal - component', () => {
   });
   it('should close modal after successful login as user', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient
-      .onGet(apiPath.userPrivileges(loginFixture.login))
-      .reply(HttpStatusCode.Ok, userPrivilegesFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
     mockedAxiosClient
       .onGet(
         apiPath.getAllUserOverlaysByCreatorQuery({
diff --git a/src/components/FunctionalArea/Modal/Modal.component.tsx b/src/components/FunctionalArea/Modal/Modal.component.tsx
index 3fb3fb373e77be1919afda00992f59caa825a57f..d913abb8ec51661208b50417a1fa090f1f3fcded 100644
--- a/src/components/FunctionalArea/Modal/Modal.component.tsx
+++ b/src/components/FunctionalArea/Modal/Modal.component.tsx
@@ -3,6 +3,7 @@ import { modalSelector } from '@/redux/modal/modal.selector';
 import dynamic from 'next/dynamic';
 import { EditOverlayModal } from './EditOverlayModal';
 import { LoginModal } from './LoginModal';
+import { ErrorReportModal } from './ErrorReportModal';
 import { ModalLayout } from './ModalLayout';
 import { OverviewImagesModal } from './OverviewImagesModal';
 import { PublicationsModal } from './PublicationsModal';
@@ -33,6 +34,11 @@ export const Modal = (): React.ReactNode => {
           <LoginModal />
         </ModalLayout>
       )}
+      {isOpen && modalName === 'error-report' && (
+        <ModalLayout>
+          <ErrorReportModal />
+        </ModalLayout>
+      )}
       {isOpen && modalName === 'publications' && <PublicationsModal />}
       {isOpen && modalName === 'edit-overlay' && (
         <ModalLayout>
diff --git a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
index d5979910d7b068b1dfdea7f79807f9083176c361..b834d91c802d23bc93587e5c91f93cff6f481832 100644
--- a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
+++ b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
@@ -28,11 +28,19 @@ export const ModalLayout = ({ children }: ModalLayoutProps): JSX.Element => {
           className={twMerge(
             'flex h-5/6 w-10/12	flex-col	overflow-hidden rounded-lg',
             modalName === 'login' && 'h-auto w-[400px]',
+            modalName === 'error-report' && 'h-auto w-[800px]',
             ['edit-overlay', 'logged-in-menu'].includes(modalName) && 'h-auto w-[432px]',
           )}
         >
           <div className="flex items-center justify-between bg-white p-[24px] text-xl">
-            <div>{modalTitle}</div>
+            {modalName === 'error-report' && (
+              <div className="font-bold text-red-500">
+                <Icon name="info" className={twMerge('mr-4 fill-red-500')} />
+                {modalTitle}
+              </div>
+            )}
+            {modalName !== 'error-report' && <div> {modalTitle} </div>}
+
             {modalName !== 'logged-in-menu' && (
               <button type="button" onClick={handleCloseModal} aria-label="close button">
                 <Icon name="close" className="fill-font-500" />
diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsModalLayout/utils/getBasePublications.test.ts b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsModalLayout/utils/getBasePublications.test.ts
index eb9a4b10c26bcb879b2e9066173d1e728f355e1c..ffa8191ae9167d7dd8bf2cdae4d0e01e8cc9ac53 100644
--- a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsModalLayout/utils/getBasePublications.test.ts
+++ b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsModalLayout/utils/getBasePublications.test.ts
@@ -1,8 +1,8 @@
 import { apiPath } from '@/redux/apiPath';
 import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { showToast } from '@/utils/showToast';
 import { PUBLICATIONS_DEFAULT_SEARCH_FIRST_10_MOCK } from '../../../../../../models/mocks/publicationsResponseMock';
-import { showToast } from '../../../../../../utils/showToast';
 import { getBasePublications } from './getBasePublications';
 
 const mockedAxiosClient = mockNetworkResponse();
diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsModalLayout/utils/getBasePublications.ts b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsModalLayout/utils/getBasePublications.ts
index 7725df112b3f7d8f4d5464a52ba0caee6e29557c..d149d03191849ea5a288b2c2c9cde031bed79ed7 100644
--- a/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsModalLayout/utils/getBasePublications.ts
+++ b/src/components/FunctionalArea/Modal/PublicationsModal/PublicationsModalLayout/utils/getBasePublications.ts
@@ -3,9 +3,9 @@ import { apiPath } from '@/redux/apiPath';
 import { PUBLICATIONS_FETCHING_ERROR_PREFIX } from '@/redux/publications/publications.constatns';
 import { axiosInstance } from '@/services/api/utils/axiosInstance';
 import { Publication, PublicationsResponse } from '@/types/models';
+import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { getErrorMessage } from '@/utils/getErrorMessage';
 import { showToast } from '@/utils/showToast';
-import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 
 interface Args {
   length: number;
@@ -26,7 +26,6 @@ export const getBasePublications = async ({ length }: Args): Promise<Publication
       type: 'error',
       message: errorMessage,
     });
-
     return [];
   }
 };
diff --git a/src/components/FunctionalArea/Modal/PublicationsModal/utils/fetchElementData.ts b/src/components/FunctionalArea/Modal/PublicationsModal/utils/fetchElementData.ts
index ceaf1b8a355e43d7c29c4c54eb8635c1f1f3233c..d7b14ea9e150beb61b66980c2f8f6f516603aea0 100644
--- a/src/components/FunctionalArea/Modal/PublicationsModal/utils/fetchElementData.ts
+++ b/src/components/FunctionalArea/Modal/PublicationsModal/utils/fetchElementData.ts
@@ -4,9 +4,9 @@ import { apiPath } from '@/redux/apiPath';
 import { BIO_ENTITY_FETCHING_ERROR_PREFIX } from '@/redux/bioEntity/bioEntity.constants';
 import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { BioEntityContent, BioEntityResponse } from '@/types/models';
-import { getErrorMessage } from '@/utils/getErrorMessage';
-import { showToast } from '@/utils/showToast';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
+import { showToast } from '@/utils/showToast';
+import { getErrorMessage } from '@/utils/getErrorMessage';
 
 export const fetchElementData = async (
   searchQuery: string,
diff --git a/src/components/FunctionalArea/TopBar/User/User.component.test.tsx b/src/components/FunctionalArea/TopBar/User/User.component.test.tsx
index 979254a81f0e7e10adbf1e92001d89da096a3c21..6198869f43d302eedd7269fe183e1622eed445a3 100644
--- a/src/components/FunctionalArea/TopBar/User/User.component.test.tsx
+++ b/src/components/FunctionalArea/TopBar/User/User.component.test.tsx
@@ -126,6 +126,7 @@ describe('AuthenticatedUser component', () => {
       loading: 'succeeded',
       login: null,
       role: null,
+      userData: null,
     });
   });
 
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 208136f0a71e569aad40d317399ece1a53c2b4f8..162b45451915d0466af4a83a2d768ae9daffc7a9 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/LoadPluginFromUrl.component.test.tsx
@@ -123,6 +123,7 @@ describe('LoadPluginFromUrl - component', () => {
       global.URL.canParse = jest.fn().mockReturnValue(true);
 
       renderComponent();
+
       const input = screen.getByTestId('load-plugin-input-url');
       expect(input).toBeVisible();
 
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
index 54276c16149fd733bf0dddae65a8db45f21624a6..5616dca84f7348306ded4a590f3de408146666f4 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
@@ -1,9 +1,9 @@
 import { PluginsManager } from '@/services/pluginsManager';
-import { showToast } from '@/utils/showToast';
 import axios from 'axios';
 import { ChangeEvent, useMemo, useState, KeyboardEvent } from 'react';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { ENTER_KEY_CODE } from '@/constants/common';
+import { showToast } from '@/utils/showToast';
+import { getErrorMessage } from '@/utils/getErrorMessage';
 import { PLUGIN_LOADING_ERROR_PREFIX } from '../../AvailablePluginsDrawer.constants';
 
 type UseLoadPluginReturnType = {
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 9f9e6faab7f10ace0507ceafdeea51385424a484..5248abdf5b3c4fb6247b99aeca83ce6f81876517 100644
--- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx
+++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlayForm/UserOverlayForm.component.test.tsx
@@ -224,6 +224,7 @@ describe('UserOverlayForm - Component', () => {
         login: 'test',
         loading: 'succeeded',
         role: 'user',
+        userData: null,
       },
       project: {
         data: projectFixture,
@@ -284,6 +285,7 @@ describe('UserOverlayForm - Component', () => {
         login: 'test',
         loading: 'succeeded',
         role: 'user',
+        userData: null,
       },
       project: {
         data: projectFixture,
diff --git a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlays.component.test.tsx b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlays.component.test.tsx
index 360c48a5e3e1fed4fdb8713a7be878c2fd9b5bd5..82c38758c84f11afeded8f09960e37938defc335 100644
--- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlays.component.test.tsx
+++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlays.component.test.tsx
@@ -29,6 +29,7 @@ describe('UserOverlays component', () => {
         error: { name: '', message: '' },
         login: null,
         role: 'user',
+        userData: null,
       },
     });
 
@@ -43,6 +44,7 @@ describe('UserOverlays component', () => {
         error: { name: '', message: '' },
         login: 'test',
         role: 'user',
+        userData: null,
       },
     });
 
@@ -56,6 +58,7 @@ describe('UserOverlays component', () => {
         error: { name: '', message: '' },
         login: 'test',
         role: 'user',
+        userData: null,
       },
     });
 
diff --git a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/UserOverlaysWithoutGroup.component.test.tsx b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/UserOverlaysWithoutGroup.component.test.tsx
index 4dc6b072685ac22f53e7585e86477c9c08f40a5c..3e3df316d994e237f0f3ed6be3010e332467816e 100644
--- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/UserOverlaysWithoutGroup.component.test.tsx
+++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/UserOverlaysWithoutGroup.component.test.tsx
@@ -45,6 +45,7 @@ describe('UserOverlaysWithoutGroup - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -82,6 +83,7 @@ describe('UserOverlaysWithoutGroup - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -104,6 +106,7 @@ describe('UserOverlaysWithoutGroup - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -148,6 +151,7 @@ describe('UserOverlaysWithoutGroup - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -186,6 +190,7 @@ describe('UserOverlaysWithoutGroup - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -237,6 +242,7 @@ describe('UserOverlaysWithoutGroup - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -279,6 +285,7 @@ describe('UserOverlaysWithoutGroup - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -328,6 +335,7 @@ describe('UserOverlaysWithoutGroup - component', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
diff --git a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/hooks/useUserOverlays.test.ts b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/hooks/useUserOverlays.test.ts
index 2f1b15654e86f62f369d013710bc9dcebad3adaf..e7b61b7bb654d8ccc8074d56a5f213612ec13399 100644
--- a/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/hooks/useUserOverlays.test.ts
+++ b/src/components/Map/Drawer/OverlaysDrawer/UserOverlays/UserOverlaysWithoutGroup/hooks/useUserOverlays.test.ts
@@ -21,6 +21,7 @@ describe('useUserOverlays', () => {
         error: DEFAULT_ERROR,
         login: null,
         role: 'user',
+        userData: null,
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -56,6 +57,7 @@ describe('useUserOverlays', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -96,6 +98,7 @@ describe('useUserOverlays', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
@@ -140,6 +143,7 @@ describe('useUserOverlays', () => {
         error: DEFAULT_ERROR,
         login: 'test',
         role: 'user',
+        userData: null,
       },
       overlays: {
         ...OVERLAYS_INITIAL_STATE_MOCK,
diff --git a/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.ts b/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.ts
index a636c57f4210f5ea5564bc93baa8e3bc37e0aecd..d98b480fe8c9e2494e841aad28dd37702c1b9c8b 100644
--- a/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/useOlMapTileLayer.ts
@@ -46,7 +46,7 @@ export const useOlMapTileLayer = (): BaseLayer => {
         url: sourceUrl,
         maxZoom: mapSize.maxZoom,
         minZoom: mapSize.minZoom,
-        tileSize: mapSize.tileSize,
+        tileSize: Math.max(mapSize.tileSize, 1),
         wrapX: OPTIONS.wrapXInTileLayer,
       }),
     [sourceUrl, mapSize.maxZoom, mapSize.minZoom, mapSize.tileSize],
diff --git a/src/constants/common.ts b/src/constants/common.ts
index 33920fa680973ef0fb027bef64903a93af288750..c3a1b1d09a4c675a5cca281cd1a02f33515bb2bd 100644
--- a/src/constants/common.ts
+++ b/src/constants/common.ts
@@ -16,6 +16,7 @@ export const NOOP = (): void => {};
 
 export const ONE_DECIMAL = 0.1;
 export const ONE_HUNDRED = 100;
+export const ONE_THOUSAND = 1000;
 
 export const EMPTY_ARRAY_STRING = '[]';
 export const ZOOM_FACTOR = 2.0; // Zoom factor indicating doubling the distance for each zoom level
diff --git a/src/models/fixtures/javaStacktraceFixture.ts b/src/models/fixtures/javaStacktraceFixture.ts
new file mode 100644
index 0000000000000000000000000000000000000000..71ed655ec26ffdb1e62b2b7e128d65a6f50a9a4a
--- /dev/null
+++ b/src/models/fixtures/javaStacktraceFixture.ts
@@ -0,0 +1,8 @@
+import { ZOD_SEED } from '@/constants';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { createFixture } from 'zod-fixture';
+import { javaStacktraceSchema } from '@/models/javaStacktraceSchema';
+
+export const javaStacktraceFixture = createFixture(javaStacktraceSchema, {
+  seed: ZOD_SEED,
+});
diff --git a/src/models/fixtures/userPrivilegesFixture.ts b/src/models/fixtures/userFixture.ts
similarity index 58%
rename from src/models/fixtures/userPrivilegesFixture.ts
rename to src/models/fixtures/userFixture.ts
index fcddc70ca1ea84b9a495a447d8760f6606529c8d..6a44bb93a6f6915a8989c622a5c635fb81b923b2 100644
--- a/src/models/fixtures/userPrivilegesFixture.ts
+++ b/src/models/fixtures/userFixture.ts
@@ -1,9 +1,9 @@
 import { ZOD_SEED } from '@/constants';
 // eslint-disable-next-line import/no-extraneous-dependencies
 import { createFixture } from 'zod-fixture';
-import { userPrivilegesSchema } from '../userPrivilegesSchema';
+import { userSchema } from '@/models/userSchema';
 
-export const userPrivilegesFixture = createFixture(userPrivilegesSchema, {
+export const userFixture = createFixture(userSchema, {
   seed: ZOD_SEED,
   array: { min: 2, max: 2 },
 });
diff --git a/src/models/javaStacktraceSchema.ts b/src/models/javaStacktraceSchema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4f9bb8c4db545a90b59c11070f745c4a4b92c70e
--- /dev/null
+++ b/src/models/javaStacktraceSchema.ts
@@ -0,0 +1,7 @@
+import { z } from 'zod';
+
+export const javaStacktraceSchema = z.object({
+  id: z.string(),
+  content: z.string(),
+  createdAt: z.string(),
+});
diff --git a/src/models/userPrivilegesSchema.ts b/src/models/userPrivilegesSchema.ts
index 28115b1a4c9ff883ac86d0f9683cc5ef139e5949..06a491461d1e4d5f2463ab5b0b13e664064b0510 100644
--- a/src/models/userPrivilegesSchema.ts
+++ b/src/models/userPrivilegesSchema.ts
@@ -1,10 +1,6 @@
 import { z } from 'zod';
 
-const userPrivilege = z.object({
+export const userPrivilegeSchema = z.object({
   privilegeType: z.string(),
   objectId: z.string().nullable(),
 });
-
-export const userPrivilegesSchema = z.object({
-  privileges: z.array(userPrivilege),
-});
diff --git a/src/models/userSchema.ts b/src/models/userSchema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..aaf1ffd817abb3d5e3ff80bf328e37c45595e3da
--- /dev/null
+++ b/src/models/userSchema.ts
@@ -0,0 +1,22 @@
+import { z } from 'zod';
+import { userPrivilegeSchema } from '@/models/userPrivilegesSchema';
+import { ZERO } from '@/constants/common';
+
+export const userSchema = z.object({
+  id: z.number().int().gt(ZERO),
+  login: z.string(),
+  name: z.string(),
+  surname: z.string(),
+  email: z.string().email().nullable(),
+  orcidId: z.string().nullable(),
+  minColor: z.string().nullable(),
+  neutralColor: z.string().nullable(),
+  simpleColor: z.string().nullable(),
+  removed: z.boolean(),
+  termsOfUseConsent: z.boolean(),
+  privileges: z.array(userPrivilegeSchema),
+  active: z.boolean(),
+  confirmed: z.boolean(),
+  ldapAccountAvailable: z.boolean(),
+  lastActive: z.string().nullable(),
+});
diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts
index d5a42e1ccc9f53ad68f2f0019108fb123d20d571..b1b26ff3c98c97eede628a3442c1659bb3775837 100644
--- a/src/redux/apiPath.ts
+++ b/src/redux/apiPath.ts
@@ -97,6 +97,9 @@ export const apiPath = {
   getAllPlugins: (): string => `/plugins/`,
   getSubmapConnections: (): string => `projects/${PROJECT_ID}/submapConnections/`,
   logout: (): string => `doLogout`,
+  user: (login: string): string => `users/${login}`,
+  getStacktrace: (code: string): string => `stacktrace/${code}`,
+  submitError: (): string => `minervanet/submitError`,
   userPrivileges: (login: string): string => `users/${login}?columns=privileges`,
   getComments: (): string => `projects/${PROJECT_ID}/comments/models/*/`,
 };
diff --git a/src/redux/backgrounds/backgrounds.reducers.test.ts b/src/redux/backgrounds/backgrounds.reducers.test.ts
index 4f70938fa505c0da1813ec8df6cf16e2f9fe4ad8..dd13a7711f9d39428ffa0ea0d3b22f90a448a962 100644
--- a/src/redux/backgrounds/backgrounds.reducers.test.ts
+++ b/src/redux/backgrounds/backgrounds.reducers.test.ts
@@ -6,6 +6,7 @@ import {
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import { apiPath } from '../apiPath';
 import backgroundsReducer from './backgrounds.slice';
 import { getAllBackgroundsByProjectId } from './backgrounds.thunks';
@@ -51,14 +52,14 @@ describe('backgrounds reducer', () => {
       .onGet(apiPath.getAllBackgroundsByProjectIdQuery(PROJECT_ID))
       .reply(HttpStatusCode.NotFound, []);
 
-    const { type, payload } = await store.dispatch(getAllBackgroundsByProjectId(PROJECT_ID));
+    const action = await store.dispatch(getAllBackgroundsByProjectId(PROJECT_ID));
     const { data, loading, error } = store.getState().backgrounds;
 
-    expect(type).toBe('backgrounds/getAllBackgroundsByProjectId/rejected');
+    expect(action.type).toBe('backgrounds/getAllBackgroundsByProjectId/rejected');
     expect(loading).toEqual('failed');
     expect(error).toEqual({ message: '', name: '' });
     expect(data).toEqual([]);
-    expect(payload).toBe(
+    expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch backgrounds: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
   });
diff --git a/src/redux/backgrounds/backgrounds.thunks.ts b/src/redux/backgrounds/backgrounds.thunks.ts
index 18a0c56bcfed6861ffabd3fb944378930dad13c4..d2ce1949ef25fd4f9768f23e63e556925be48b2b 100644
--- a/src/redux/backgrounds/backgrounds.thunks.ts
+++ b/src/redux/backgrounds/backgrounds.thunks.ts
@@ -4,14 +4,14 @@ 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 { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import { BACKGROUNDS_FETCHING_ERROR_PREFIX } from './backgrounds.constants';
 
 export const getAllBackgroundsByProjectId = createAsyncThunk<MapBackground[], string, ThunkConfig>(
   'backgrounds/getAllBackgroundsByProjectId',
-  async (projectId: string, { rejectWithValue }) => {
+  async (projectId: string) => {
     try {
       const response = await axiosInstance.get<MapBackground[]>(
         apiPath.getAllBackgroundsByProjectIdQuery(projectId),
@@ -21,9 +21,7 @@ export const getAllBackgroundsByProjectId = createAsyncThunk<MapBackground[], st
 
       return isDataValid ? response.data : [];
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: BACKGROUNDS_FETCHING_ERROR_PREFIX });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: BACKGROUNDS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/bioEntity/bioEntity.reducers.test.ts b/src/redux/bioEntity/bioEntity.reducers.test.ts
index d48998d83951e3289f1da610ff3f62915a5c3281..07af4ebe2cc8d18f49b353fe759039125617c1cf 100644
--- a/src/redux/bioEntity/bioEntity.reducers.test.ts
+++ b/src/redux/bioEntity/bioEntity.reducers.test.ts
@@ -7,6 +7,7 @@ import {
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import bioEntityContentsReducer from './bioEntity.slice';
 import { getBioEntity } from './bioEntity.thunks';
 import { BioEntityContentsState } from './bioEntity.types';
@@ -14,6 +15,8 @@ import { BioEntityContentsState } from './bioEntity.types';
 const mockedAxiosClient = mockNetworkNewAPIResponse();
 const SEARCH_QUERY = 'park7';
 
+jest.mock('../../utils/error-report/errorReporting');
+
 const INITIAL_STATE: BioEntityContentsState = {
   data: [],
   loading: 'idle',
@@ -77,7 +80,7 @@ describe('bioEntity reducer', () => {
       )
       .reply(HttpStatusCode.NotFound, bioEntityResponseFixture);
 
-    const { type, payload } = await store.dispatch(
+    const action = await store.dispatch(
       getBioEntity({
         searchQuery: SEARCH_QUERY,
         isPerfectMatch: false,
@@ -85,14 +88,14 @@ describe('bioEntity reducer', () => {
     );
     const { data } = store.getState().bioEntity;
 
-    const bioEnityWithSearchElement = data.find(
+    const bioEntityWithSearchElement = data.find(
       bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY,
     );
-    expect(type).toBe('project/getBioEntityContents/rejected');
-    expect(payload).toBe(
+    expect(action.type).toBe('project/getBioEntityContents/rejected');
+    expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch bio entity: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
-    expect(bioEnityWithSearchElement).toEqual({
+    expect(bioEntityWithSearchElement).toEqual({
       searchQueryElement: SEARCH_QUERY,
       data: undefined,
       loading: 'failed',
@@ -118,11 +121,11 @@ describe('bioEntity reducer', () => {
     );
 
     const { data } = store.getState().bioEntity;
-    const bioEnityWithSearchElement = data.find(
+    const bioEntityWithSearchElement = data.find(
       bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY,
     );
 
-    expect(bioEnityWithSearchElement).toEqual({
+    expect(bioEntityWithSearchElement).toEqual({
       searchQueryElement: SEARCH_QUERY,
       data: undefined,
       loading: 'pending',
@@ -132,11 +135,11 @@ describe('bioEntity reducer', () => {
     bioEntityContentsPromise.then(() => {
       const { data: dataPromiseFulfilled } = store.getState().bioEntity;
 
-      const bioEnityWithSearchElementFulfilled = dataPromiseFulfilled.find(
+      const bioEntityWithSearchElementFulfilled = dataPromiseFulfilled.find(
         bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY,
       );
 
-      expect(bioEnityWithSearchElementFulfilled).toEqual({
+      expect(bioEntityWithSearchElementFulfilled).toEqual({
         searchQueryElement: SEARCH_QUERY,
         data: bioEntityResponseFixture.content,
         loading: 'succeeded',
diff --git a/src/redux/bioEntity/bioEntity.thunks.test.ts b/src/redux/bioEntity/bioEntity.thunks.test.ts
index f2b54f3abdd5a5e258c51bfc8d224a3877d02fdf..fb433fb0fb0b18033b883c6fa8213432f5f3260b 100644
--- a/src/redux/bioEntity/bioEntity.thunks.test.ts
+++ b/src/redux/bioEntity/bioEntity.thunks.test.ts
@@ -6,10 +6,13 @@ import {
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import contentsReducer from './bioEntity.slice';
 import { getBioEntity, getMultiBioEntity } from './bioEntity.thunks';
 import { BioEntityContentsState } from './bioEntity.types';
 
+jest.mock('../../utils/error-report/errorReporting');
+
 const mockedAxiosClient = mockNetworkNewAPIResponse();
 const SEARCH_QUERY = 'park7';
 
@@ -65,13 +68,13 @@ describe('bioEntityContents thunks', () => {
         )
         .reply(HttpStatusCode.NotFound, null);
 
-      const { payload } = await store.dispatch(
+      const action = await store.dispatch(
         getBioEntity({
           searchQuery: SEARCH_QUERY,
           isPerfectMatch: false,
         }),
       );
-      expect(payload).toEqual(
+      expect(() => unwrapResult(action)).toThrow(
         "Failed to fetch bio entity: The page you're looking for doesn't exist. Please verify the URL and try again.",
       );
     });
diff --git a/src/redux/bioEntity/thunks/getBioEntity.ts b/src/redux/bioEntity/thunks/getBioEntity.ts
index f8a302ee49a3d97ea240da6bbad3f282b0bc0355..bf54870a8db007d3785bb07606516fa293044a6f 100644
--- a/src/redux/bioEntity/thunks/getBioEntity.ts
+++ b/src/redux/bioEntity/thunks/getBioEntity.ts
@@ -4,9 +4,9 @@ import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { BioEntityContent, BioEntityResponse } from '@/types/models';
 import { PerfectSearchParams } from '@/types/search';
 import { ThunkConfig } from '@/types/store';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
+import { getError } from '@/utils/error-report/getError';
 import { addNumbersToEntityNumberData } from '../../entityNumber/entityNumber.slice';
 import { BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants';
 
@@ -18,10 +18,7 @@ export const getBioEntity = createAsyncThunk<
   ThunkConfig
 >(
   'project/getBioEntityContents',
-  async (
-    { searchQuery, isPerfectMatch, addNumbersToEntityNumber = true },
-    { rejectWithValue, dispatch },
-  ) => {
+  async ({ searchQuery, isPerfectMatch, addNumbersToEntityNumber = true }, { dispatch }) => {
     try {
       const response = await axiosInstanceNewAPI.get<BioEntityResponse>(
         apiPath.getBioEntityContentsStringWithQuery({ searchQuery, isPerfectMatch }),
@@ -39,11 +36,7 @@ export const getBioEntity = createAsyncThunk<
 
       return isDataValidBioEnity ? response.data.content : undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({
-        error,
-        prefix: BIO_ENTITY_FETCHING_ERROR_PREFIX,
-      });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: BIO_ENTITY_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/bioEntity/thunks/getMultiBioEntity.ts b/src/redux/bioEntity/thunks/getMultiBioEntity.ts
index c8a38ef3aa39a081bf0351fa166c074b509d5eaf..948156156324bc4cb4d9ff0e846f7dfc97fb8284 100644
--- a/src/redux/bioEntity/thunks/getMultiBioEntity.ts
+++ b/src/redux/bioEntity/thunks/getMultiBioEntity.ts
@@ -3,8 +3,8 @@ import type { AppDispatch, store } from '@/redux/store';
 import { BioEntityContent } from '@/types/models';
 import { PerfectMultiSearchParams } from '@/types/search';
 import { ThunkConfig } from '@/types/store';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { PayloadAction, createAsyncThunk } from '@reduxjs/toolkit';
+import { getError } from '@/utils/error-report/getError';
 import { addNumbersToEntityNumberData } from '../../entityNumber/entityNumber.slice';
 import { MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants';
 import { getBioEntity } from './getBioEntity';
@@ -20,7 +20,7 @@ export const getMultiBioEntity = createAsyncThunk<
 >(
   'project/getMultiBioEntity',
   // eslint-disable-next-line consistent-return
-  async ({ searchQueries, isPerfectMatch }, { dispatch, rejectWithValue, getState }) => {
+  async ({ searchQueries, isPerfectMatch }, { dispatch, getState }) => {
     try {
       const asyncGetBioEntityFunctions = searchQueries.map(searchQuery =>
         dispatch(getBioEntity({ searchQuery, isPerfectMatch, addNumbersToEntityNumber: false })),
@@ -50,12 +50,7 @@ export const getMultiBioEntity = createAsyncThunk<
 
       return bioEntityContents;
     } catch (error) {
-      const errorMessage = getErrorMessage({
-        error,
-        prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX,
-      });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts b/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts
index bfda62b8ed94d82ddb73c8991053aac611b5f725..e50189938bbe9b45e5fa38601d799c327785df2f 100644
--- a/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts
+++ b/src/redux/bioEntity/thunks/getSubmapConnectionsBioEntity.ts
@@ -3,16 +3,15 @@ import { submapConnection } from '@/models/submapConnection';
 import { apiPath } from '@/redux/apiPath';
 import { axiosInstance, axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { BioEntityContent, BioEntityResponse, SubmapConnection } from '@/types/models';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { getError } from '@/utils/error-report/getError';
 import { MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX } from '../bioEntity.constants';
 
 export const getSubmapConnectionsBioEntity = createAsyncThunk<BioEntityContent[]>(
   'project/getSubmapConnectionsBioEntity',
-  // eslint-disable-next-line consistent-return
-  async (_, { rejectWithValue }) => {
+  async () => {
     try {
       const response = await axiosInstance.get<SubmapConnection[]>(apiPath.getSubmapConnections());
 
@@ -39,12 +38,7 @@ export const getSubmapConnectionsBioEntity = createAsyncThunk<BioEntityContent[]
 
       return bioEntityContents;
     } catch (error) {
-      const errorMessage = getErrorMessage({
-        error,
-        prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX,
-      });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: MULTI_BIO_ENTITY_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/chemicals/chemicals.reducers.test.ts b/src/redux/chemicals/chemicals.reducers.test.ts
index 9b66afe34421293ef0e89ec2b02b45767c5c151c..a877f38ea214c68ba8609f4645d53c417c99c5c6 100644
--- a/src/redux/chemicals/chemicals.reducers.test.ts
+++ b/src/redux/chemicals/chemicals.reducers.test.ts
@@ -7,6 +7,7 @@ import {
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import chemicalsReducer from './chemicals.slice';
 import { getChemicals } from './chemicals.thunks';
 import { ChemicalsState } from './chemicals.types';
@@ -57,15 +58,15 @@ describe('chemicals reducer', () => {
       .onGet(apiPath.getChemicalsStringWithQuery(SEARCH_QUERY))
       .reply(HttpStatusCode.NotFound, chemicalsFixture);
 
-    const { type, payload } = await store.dispatch(getChemicals(SEARCH_QUERY));
+    const action = await store.dispatch(getChemicals(SEARCH_QUERY));
     const { data } = store.getState().chemicals;
 
     const chemicalsWithSearchElement = data.find(
       bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY,
     );
 
-    expect(type).toBe('project/getChemicals/rejected');
-    expect(payload).toBe(
+    expect(action.type).toBe('project/getChemicals/rejected');
+    expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch chemicals: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
     expect(chemicalsWithSearchElement).toEqual({
diff --git a/src/redux/chemicals/chemicals.thunks.test.ts b/src/redux/chemicals/chemicals.thunks.test.ts
index 73cb2d0ef46659c702a4cda23ea6eda640bb871e..7a93ec084524cd7a3dd6ea61675088377a08b789 100644
--- a/src/redux/chemicals/chemicals.thunks.test.ts
+++ b/src/redux/chemicals/chemicals.thunks.test.ts
@@ -6,6 +6,7 @@ import {
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import chemicalsReducer from './chemicals.slice';
 import { getChemicals } from './chemicals.thunks';
 import { ChemicalsState } from './chemicals.types';
@@ -13,12 +14,14 @@ import { ChemicalsState } from './chemicals.types';
 const mockedAxiosClient = mockNetworkNewAPIResponse();
 const SEARCH_QUERY = 'Corticosterone';
 
+jest.mock('../../utils/error-report/errorReporting');
+
 describe('chemicals thunks', () => {
   let store = {} as ToolkitStoreWithSingleSlice<ChemicalsState>;
   beforeEach(() => {
     store = createStoreInstanceUsingSliceReducer('chemicals', chemicalsReducer);
   });
-  describe('getChemiclas', () => {
+  describe('getChemicals', () => {
     it('should return data when data response from API is valid', async () => {
       mockedAxiosClient
         .onGet(apiPath.getChemicalsStringWithQuery(SEARCH_QUERY))
@@ -35,13 +38,13 @@ describe('chemicals thunks', () => {
       const { payload } = await store.dispatch(getChemicals(SEARCH_QUERY));
       expect(payload).toEqual(undefined);
     });
-    it('should handle error message when getChemiclas failed ', async () => {
+    it('should handle error message when getChemicals failed ', async () => {
       mockedAxiosClient
         .onGet(apiPath.getChemicalsStringWithQuery(SEARCH_QUERY))
         .reply(HttpStatusCode.Forbidden, { randomProperty: 'randomValue' });
 
-      const { payload } = await store.dispatch(getChemicals(SEARCH_QUERY));
-      expect(payload).toEqual(
+      const action = await store.dispatch(getChemicals(SEARCH_QUERY));
+      expect(() => unwrapResult(action)).toThrow(
         "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 8a2f9878eb66b14c781d3ad69e484cf83efe6c6d..8553d6a4f3d06bbc8fbf50073c4c18ee53e70b63 100644
--- a/src/redux/chemicals/chemicals.thunks.ts
+++ b/src/redux/chemicals/chemicals.thunks.ts
@@ -3,10 +3,10 @@ import { apiPath } from '@/redux/apiPath';
 import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { Chemical } from '@/types/models';
 import { ThunkConfig } from '@/types/store';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { getError } from '@/utils/error-report/getError';
 import { addNumbersToEntityNumberData } from '../entityNumber/entityNumber.slice';
 import {
   CHEMICALS_FETCHING_ERROR_PREFIX,
@@ -15,7 +15,7 @@ import {
 
 export const getChemicals = createAsyncThunk<Chemical[] | undefined, string, ThunkConfig>(
   'project/getChemicals',
-  async (searchQuery, { rejectWithValue }) => {
+  async searchQuery => {
     try {
       const response = await axiosInstanceNewAPI.get<Chemical[]>(
         apiPath.getChemicalsStringWithQuery(searchQuery),
@@ -25,8 +25,7 @@ export const getChemicals = createAsyncThunk<Chemical[] | undefined, string, Thu
 
       return isDataValid ? response.data : undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: CHEMICALS_FETCHING_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: CHEMICALS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
@@ -34,7 +33,7 @@ export const getChemicals = createAsyncThunk<Chemical[] | undefined, string, Thu
 export const getMultiChemicals = createAsyncThunk<void, string[], ThunkConfig>(
   'project/getMultChemicals',
   // eslint-disable-next-line consistent-return
-  async (searchQueries, { dispatch, rejectWithValue }) => {
+  async (searchQueries, { dispatch }) => {
     try {
       const asyncGetChemicalsFunctions = searchQueries.map(searchQuery =>
         dispatch(getChemicals(searchQuery)),
@@ -55,12 +54,7 @@ export const getMultiChemicals = createAsyncThunk<void, string[], ThunkConfig>(
       const chemicalsIds = chemicalsTargetsData.map(d => d.elementId);
       dispatch(addNumbersToEntityNumberData(chemicalsIds));
     } catch (error) {
-      const errorMessage = getErrorMessage({
-        error,
-        prefix: MULTI_CHEMICALS_FETCHING_ERROR_PREFIX,
-      });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: MULTI_CHEMICALS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts b/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
index 94d445b845aa63f1c45fef92ea66a5a75a05fd00..1df36392927a3d24ea6fd7b64d7e11043c11a205 100644
--- a/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
+++ b/src/redux/compartmentPathways/compartmentPathways.reducers.test.ts
@@ -11,6 +11,7 @@ import {
   compartmentPathwaysOverLimitFixture,
 } from '@/models/fixtures/compartmentPathways';
 import { getModelsIds } from '@/components/Map/Drawer/ExportDrawer/ExportDrawer.component.utils';
+import { unwrapResult } from '@reduxjs/toolkit';
 import { apiPath } from '../apiPath';
 import compartmentPathwaysReducer from './compartmentPathways.slice';
 import { CompartmentPathwaysState } from './compartmentPathways.types';
@@ -114,7 +115,7 @@ describe('compartmentPathways reducer', () => {
 
     const dispatchData = await compartmentPathwaysPromise;
 
-    expect(dispatchData.payload).toBe(
+    expect(() => unwrapResult(dispatchData)).toThrow(
       "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;
diff --git a/src/redux/compartmentPathways/compartmentPathways.thunks.ts b/src/redux/compartmentPathways/compartmentPathways.thunks.ts
index b8143dbe2627fe7239a9eadf8546497e70b5bbfe..8f1bd216b8ecbff5f0cd4e608a7ee8737b9e9ad8 100644
--- a/src/redux/compartmentPathways/compartmentPathways.thunks.ts
+++ b/src/redux/compartmentPathways/compartmentPathways.thunks.ts
@@ -8,7 +8,7 @@ import {
   compartmentPathwaySchema,
 } from '@/models/compartmentPathwaySchema';
 import { z } from 'zod';
-import { getErrorMessage } from '@/utils/getErrorMessage';
+import { getError } from '@/utils/error-report/getError';
 import {
   COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX,
   MAX_NUMBER_OF_IDS_IN_GET_QUERY,
@@ -116,18 +116,14 @@ export const fetchCompartmentPathways = async (
 
 export const getCompartmentPathways = createAsyncThunk(
   'compartmentPathways/getCompartmentPathways',
-  async (modelsIds: number[] | undefined, { rejectWithValue }) => {
+  async (modelsIds: number[] | undefined) => {
     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);
+      return Promise.reject(getError({ error, prefix: COMPARMENT_PATHWAYS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/configuration/configuration.thunks.ts b/src/redux/configuration/configuration.thunks.ts
index 8b4db5ea19083cc0f044966eb567cc12610aa66f..6b03cfa68a9fa4484528c02bc276a7f72d866f34 100644
--- a/src/redux/configuration/configuration.thunks.ts
+++ b/src/redux/configuration/configuration.thunks.ts
@@ -5,8 +5,8 @@ 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 { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import {
   CONFIGURATION_FETCHING_ERROR_PREFIX,
@@ -17,7 +17,7 @@ export const getConfigurationOptions = createAsyncThunk<
   ConfigurationOption[] | undefined,
   void,
   ThunkConfig
->('configuration/getConfigurationOptions', async (_, { rejectWithValue }) => {
+>('configuration/getConfigurationOptions', async () => {
   try {
     const response = await axiosInstance.get<ConfigurationOption[]>(
       apiPath.getConfigurationOptions(),
@@ -30,17 +30,13 @@ export const getConfigurationOptions = createAsyncThunk<
 
     return isDataValid ? response.data : undefined;
   } catch (error) {
-    const errorMessage = getErrorMessage({
-      error,
-      prefix: CONFIGURATION_OPTIONS_FETCHING_ERROR_PREFIX,
-    });
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: CONFIGURATION_OPTIONS_FETCHING_ERROR_PREFIX }));
   }
 });
 
 export const getConfiguration = createAsyncThunk<Configuration | undefined, void, ThunkConfig>(
   'configuration/getConfiguration',
-  async (_, { rejectWithValue }) => {
+  async () => {
     try {
       const response = await axiosInstance.get<Configuration>(apiPath.getConfiguration());
 
@@ -48,8 +44,7 @@ export const getConfiguration = createAsyncThunk<Configuration | undefined, void
 
       return isDataValid ? response.data : undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: CONFIGURATION_FETCHING_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: CONFIGURATION_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/constant/constant.thunks.ts b/src/redux/constant/constant.thunks.ts
index c939e0812f6bc36ecc195e51dd4226515b435408..9fb31a768864e749ee437b078c462e74a6390411 100644
--- a/src/redux/constant/constant.thunks.ts
+++ b/src/redux/constant/constant.thunks.ts
@@ -1,12 +1,12 @@
 import { createAsyncThunk } from '@reduxjs/toolkit';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { ThunkConfig } from '@/types/store';
 import { ConstantType } from '@/redux/constant/constant.types';
 import { getConfigValue } from '@/constants/index.utils';
+import { getError } from '@/utils/error-report/getError';
 
 export const getConstant = createAsyncThunk<ConstantType | undefined, void, ThunkConfig>(
   'constant/getConstant',
-  async (_, { rejectWithValue }) => {
+  async () => {
     try {
       const apiBaseUrl = getConfigValue('BASE_API_URL');
       const result: ConstantType = {
@@ -15,8 +15,7 @@ export const getConstant = createAsyncThunk<ConstantType | undefined, void, Thun
       };
       return result;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: 'Failed to build constants' });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: 'Failed to build constants' }));
     }
   },
 );
diff --git a/src/redux/drawer/drawer.thunks.ts b/src/redux/drawer/drawer.thunks.ts
index f08955f9c5aafd0d79a7b960fe584abf7b688ac1..a590ad90d775be513a15646b8f8f523cfed59aa2 100644
--- a/src/redux/drawer/drawer.thunks.ts
+++ b/src/redux/drawer/drawer.thunks.ts
@@ -6,7 +6,7 @@ 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 { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import {
   CHEMICALS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX,
@@ -36,7 +36,7 @@ const getDrugsByName = async (drugName: string): Promise<Drug[]> => {
 
 export const getDrugsForBioEntityDrawerTarget = createAsyncThunk<Drug[], string, ThunkConfig>(
   'drawer/getDrugsForBioEntityDrawerTarget',
-  async (target, { rejectWithValue }) => {
+  async target => {
     try {
       const drugsNames = await getDrugsNamesForTarget(target);
       const drugsArrays = await Promise.all(
@@ -46,12 +46,9 @@ export const getDrugsForBioEntityDrawerTarget = createAsyncThunk<Drug[], string,
 
       return drugs;
     } catch (error) {
-      const errorMessage = getErrorMessage({
-        error,
-        prefix: DRUGS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX,
-      });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(
+        getError({ error, prefix: DRUGS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX }),
+      );
     }
   },
 );
@@ -82,7 +79,7 @@ export const getChemicalsForBioEntityDrawerTarget = createAsyncThunk<
   Chemical[],
   string,
   ThunkConfig
->('drawer/getChemicalsForBioEntityDrawerTarget', async (target, { rejectWithValue }) => {
+>('drawer/getChemicalsForBioEntityDrawerTarget', async target => {
   try {
     const chemicalsNames = await getChemicalsNamesForTarget(target);
     const chemicalsArrays = await Promise.all(
@@ -92,11 +89,8 @@ export const getChemicalsForBioEntityDrawerTarget = createAsyncThunk<
 
     return chemicals;
   } catch (error) {
-    const errorMessage = getErrorMessage({
-      error,
-      prefix: CHEMICALS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX,
-    });
-
-    return rejectWithValue(errorMessage);
+    return Promise.reject(
+      getError({ error, prefix: CHEMICALS_FOR_BIO_ENTITY_FETCHING_ERROR_PREFIX }),
+    );
   }
 });
diff --git a/src/redux/drugs/drugs.reducers.test.ts b/src/redux/drugs/drugs.reducers.test.ts
index f6e6c671bc29975194a163390e717a5bc91275e3..69d29267ef92cdddead5846ce3655c0785b3c2d7 100644
--- a/src/redux/drugs/drugs.reducers.test.ts
+++ b/src/redux/drugs/drugs.reducers.test.ts
@@ -7,6 +7,7 @@ import {
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import drugsReducer from './drugs.slice';
 import { getDrugs } from './drugs.thunks';
 import { DrugsState } from './drugs.types';
@@ -56,16 +57,16 @@ describe('drugs reducer', () => {
       .onGet(apiPath.getDrugsStringWithQuery(SEARCH_QUERY))
       .reply(HttpStatusCode.NotFound, []);
 
-    const { type, payload } = await store.dispatch(getDrugs(SEARCH_QUERY));
+    const action = await store.dispatch(getDrugs(SEARCH_QUERY));
     const { data } = store.getState().drugs;
     const drugsWithSearchElement = data.find(
       bioEntity => bioEntity.searchQueryElement === SEARCH_QUERY,
     );
 
-    expect(payload).toBe(
+    expect(() => unwrapResult(action)).toThrow(
       "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(action.type).toBe('project/getDrugs/rejected');
     expect(drugsWithSearchElement).toEqual({
       searchQueryElement: SEARCH_QUERY,
       data: undefined,
diff --git a/src/redux/drugs/drugs.thunks.ts b/src/redux/drugs/drugs.thunks.ts
index f837f49d662ef6bfe3b7fef5558a43d0caf3434a..c327e5cd80c970b41c3318451e26c599ac655d4a 100644
--- a/src/redux/drugs/drugs.thunks.ts
+++ b/src/redux/drugs/drugs.thunks.ts
@@ -3,16 +3,16 @@ import { apiPath } from '@/redux/apiPath';
 import { axiosInstanceNewAPI } from '@/services/api/utils/axiosInstance';
 import { Drug } from '@/types/models';
 import { ThunkConfig } from '@/types/store';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { getError } from '@/utils/error-report/getError';
 import { addNumbersToEntityNumberData } from '../entityNumber/entityNumber.slice';
 import { DRUGS_FETCHING_ERROR_PREFIX, MULTI_DRUGS_FETCHING_ERROR_PREFIX } from './drugs.constants';
 
 export const getDrugs = createAsyncThunk<Drug[] | undefined, string, ThunkConfig>(
   'project/getDrugs',
-  async (searchQuery: string, { rejectWithValue }) => {
+  async (searchQuery: string) => {
     try {
       const response = await axiosInstanceNewAPI.get<Drug[]>(
         apiPath.getDrugsStringWithQuery(searchQuery),
@@ -22,8 +22,7 @@ export const getDrugs = createAsyncThunk<Drug[] | undefined, string, ThunkConfig
 
       return isDataValid ? response.data : undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: DRUGS_FETCHING_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: DRUGS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
@@ -31,7 +30,7 @@ export const getDrugs = createAsyncThunk<Drug[] | undefined, string, ThunkConfig
 export const getMultiDrugs = createAsyncThunk<void, string[], ThunkConfig>(
   'project/getMultiDrugs',
   // eslint-disable-next-line consistent-return
-  async (searchQueries, { dispatch, rejectWithValue }) => {
+  async (searchQueries, { dispatch }) => {
     try {
       const asyncGetDrugsFunctions = searchQueries.map(searchQuery =>
         dispatch(getDrugs(searchQuery)),
@@ -52,9 +51,7 @@ export const getMultiDrugs = createAsyncThunk<void, string[], ThunkConfig>(
       const drugsIds = drugsTargetsData.map(d => d.elementId);
       dispatch(addNumbersToEntityNumberData(drugsIds));
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: MULTI_DRUGS_FETCHING_ERROR_PREFIX });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: MULTI_DRUGS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/export/export.reducers.test.ts b/src/redux/export/export.reducers.test.ts
index 778aca4f95a58b094b126f449643804fcab85287..40e92e5cce3ba3acebf5ad28dbc7b4c1f5afecfe 100644
--- a/src/redux/export/export.reducers.test.ts
+++ b/src/redux/export/export.reducers.test.ts
@@ -4,6 +4,7 @@ import {
   createStoreInstanceUsingSliceReducer,
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import { ExportState } from './export.types';
 import exportReducer from './export.slice';
 import { apiPath } from '../apiPath';
@@ -76,7 +77,7 @@ describe('export reducer', () => {
     mockedAxiosClient
       .onPost(apiPath.downloadNetworkCsv())
       .reply(HttpStatusCode.NotFound, undefined);
-    const { payload, type } = await store.dispatch(
+    const action = await store.dispatch(
       downloadNetwork({
         annotations: [],
         columns: [],
@@ -85,8 +86,8 @@ describe('export reducer', () => {
         submaps: [],
       }),
     );
-    expect(type).toBe('export/downloadNetwork/rejected');
-    expect(payload).toBe(
+    expect(action.type).toBe('export/downloadNetwork/rejected');
+    expect(() => unwrapResult(action)).toThrow(
       "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;
@@ -135,7 +136,7 @@ describe('export reducer', () => {
     mockedAxiosClient
       .onPost(apiPath.downloadElementsCsv())
       .reply(HttpStatusCode.NotFound, undefined);
-    const { payload } = await store.dispatch(
+    const action = await store.dispatch(
       downloadElements({
         annotations: [],
         columns: [],
@@ -147,7 +148,7 @@ describe('export reducer', () => {
     const { loading } = store.getState().export.downloadElements;
 
     expect(loading).toEqual('failed');
-    expect(payload).toEqual(
+    expect(() => unwrapResult(action)).toThrow(
       "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 bf49e0b04e79e1eea61cac05f2eb79810b23ce55..ccb5f74d412d0963fbd420b3a662ab1ee8c89f5e 100644
--- a/src/redux/export/export.thunks.ts
+++ b/src/redux/export/export.thunks.ts
@@ -5,8 +5,8 @@ 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 { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import { downloadFileFromBlob } from './export.utils';
 import { ELEMENTS_DOWNLOAD_ERROR_PREFIX, NETWORK_DOWNLOAD_ERROR_PREFIX } from './export.constants';
@@ -24,7 +24,7 @@ export const downloadElements = createAsyncThunk<
   DownloadElementsBodyRequest,
   ThunkConfig
   // eslint-disable-next-line consistent-return
->('export/downloadElements', async (data, { rejectWithValue }) => {
+>('export/downloadElements', async data => {
   try {
     const response = await axiosInstanceNewAPI.post<ExportElements>(
       apiPath.downloadElementsCsv(),
@@ -40,9 +40,7 @@ export const downloadElements = createAsyncThunk<
       downloadFileFromBlob(response.data, `${PROJECT_ID}-elementExport.csv`);
     }
   } catch (error) {
-    const errorMessage = getErrorMessage({ error, prefix: ELEMENTS_DOWNLOAD_ERROR_PREFIX });
-
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: ELEMENTS_DOWNLOAD_ERROR_PREFIX }));
   }
 });
 
@@ -57,7 +55,7 @@ type DownloadNetworkBodyRequest = {
 export const downloadNetwork = createAsyncThunk<undefined, DownloadNetworkBodyRequest, ThunkConfig>(
   'export/downloadNetwork',
   // eslint-disable-next-line consistent-return
-  async (data, { rejectWithValue }) => {
+  async data => {
     try {
       const response = await axiosInstanceNewAPI.post<ExportNetwork>(
         apiPath.downloadNetworkCsv(),
@@ -73,9 +71,7 @@ export const downloadNetwork = createAsyncThunk<undefined, DownloadNetworkBodyRe
         downloadFileFromBlob(response.data, `${PROJECT_ID}-networkExport.csv`);
       }
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: NETWORK_DOWNLOAD_ERROR_PREFIX });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: NETWORK_DOWNLOAD_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/map/map.thunks.ts b/src/redux/map/map.thunks.ts
index 05b675bba64d223d63cab0865e8692f5f9620da4..0ea2c2ea5766dcee135c80d56ab3122a3cc6217e 100644
--- a/src/redux/map/map.thunks.ts
+++ b/src/redux/map/map.thunks.ts
@@ -5,8 +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 { getError } from '@/utils/error-report/getError';
 import type { AppDispatch, RootState } from '../store';
 import {
   InitMapBackgroundActionPayload,
@@ -145,15 +145,13 @@ export const initMapSizeAndModelId = createAsyncThunk<
   InitMapSizeAndModelIdActionPayload,
   InitMapSizeAndModelIdParams,
   { dispatch: AppDispatch; state: RootState } & ThunkConfig
->('map/initMapSizeAndModelId', async ({ queryData }, { getState, rejectWithValue }) => {
+>('map/initMapSizeAndModelId', async ({ queryData }, { getState }) => {
   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);
+    return Promise.reject(getError({ error, prefix: INIT_MAP_SIZE_MODEL_ID_ERROR_PREFIX }));
   }
 });
 
@@ -161,15 +159,13 @@ export const initMapPosition = createAsyncThunk<
   InitMapPositionActionPayload,
   InitMapPositionParams,
   { dispatch: AppDispatch; state: RootState } & ThunkConfig
->('map/initMapPosition', async ({ queryData }, { getState, rejectWithValue }) => {
+>('map/initMapPosition', async ({ queryData }, { getState }) => {
   try {
     const state = getState();
 
     return getInitMapPosition(state, queryData);
   } catch (error) {
-    const errorMessage = getErrorMessage({ error, prefix: INIT_MAP_POSITION_ERROR_PREFIX });
-
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: INIT_MAP_POSITION_ERROR_PREFIX }));
   }
 });
 
@@ -177,14 +173,12 @@ export const initMapBackground = createAsyncThunk<
   InitMapBackgroundActionPayload,
   InitMapBackgroundParams,
   { dispatch: AppDispatch; state: RootState } & ThunkConfig
->('map/initMapBackground', async ({ queryData }, { getState, rejectWithValue }) => {
+>('map/initMapBackground', async ({ queryData }, { getState }) => {
   try {
     const state = getState();
     return getBackgroundId(state, queryData);
   } catch (error) {
-    const errorMessage = getErrorMessage({ error, prefix: INIT_MAP_BACKGROUND_ERROR_PREFIX });
-
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: INIT_MAP_BACKGROUND_ERROR_PREFIX }));
   }
 });
 
@@ -192,14 +186,12 @@ export const initOpenedMaps = createAsyncThunk<
   InitOpenedMapsActionPayload,
   InitOpenedMapsProps,
   { dispatch: AppDispatch; state: RootState } & ThunkConfig
->('appInit/initOpenedMaps', async ({ queryData }, { getState, rejectWithValue }) => {
+>('appInit/initOpenedMaps', async ({ queryData }, { getState }) => {
   try {
     const state = getState();
 
     return getOpenedMaps(state, queryData);
   } catch (error) {
-    const errorMessage = getErrorMessage({ error, prefix: INIT_OPENED_MAPS_ERROR_PREFIX });
-
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: INIT_OPENED_MAPS_ERROR_PREFIX }));
   }
 });
diff --git a/src/redux/middlewares/error.middleware.test.ts b/src/redux/middlewares/error.middleware.test.ts
index 7662714e2f08a2dccd3a6329db08716d0103bc2d..6c34711b000f25d6642c79fdf7068a4b16f47913 100644
--- a/src/redux/middlewares/error.middleware.test.ts
+++ b/src/redux/middlewares/error.middleware.test.ts
@@ -1,16 +1,17 @@
+import { store } from '@/redux/store';
 import { showToast } from '@/utils/showToast';
 import { errorMiddlewareListener } from './error.middleware';
 
-jest.mock('../../utils/showToast', () => ({
-  showToast: jest.fn(),
-}));
+jest.mock('../../utils/showToast');
 
 describe('errorMiddlewareListener', () => {
+  const dispatchSpy = jest.spyOn(store, 'dispatch');
+
   beforeEach(() => {
     jest.clearAllMocks();
   });
 
-  it('should show toast with error message when action is rejected with value', async () => {
+  it('should handle error with message when action is rejected', async () => {
     const action = {
       type: 'action/rejected',
       payload: 'Error message',
@@ -19,12 +20,23 @@ describe('errorMiddlewareListener', () => {
         rejectedWithValue: true,
         requestStatus: 'rejected',
       },
+      error: {
+        code: 'Error 2',
+      },
     };
-    await errorMiddlewareListener(action);
-    expect(showToast).toHaveBeenCalledWith({ type: 'error', message: 'Error message' });
+    const { getState, dispatch } = store;
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-expect-error
+    await errorMiddlewareListener(action, { getState, dispatch });
+    expect(dispatchSpy).toHaveBeenCalledWith(
+      expect.objectContaining({
+        type: 'modal/openErrorReportModal',
+        payload: expect.anything(),
+      }),
+    );
   });
 
-  it('should show toast with unknown error when action is rejected without value', async () => {
+  it('should handle error without message when action is rejected', async () => {
     const action = {
       type: 'action/rejected',
       payload: null,
@@ -33,15 +45,23 @@ describe('errorMiddlewareListener', () => {
         rejectedWithValue: true,
         requestStatus: 'rejected',
       },
+      error: {
+        code: 'Error 3',
+      },
     };
-    await errorMiddlewareListener(action);
-    expect(showToast).toHaveBeenCalledWith({
-      type: 'error',
-      message: 'An unknown error occurred. Please try again later.',
-    });
+    const { getState, dispatch } = store;
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-expect-error
+    await errorMiddlewareListener(action, { getState, dispatch });
+    expect(dispatchSpy).toHaveBeenCalledWith(
+      expect.objectContaining({
+        type: 'modal/openErrorReportModal',
+        payload: expect.anything(),
+      }),
+    );
   });
 
-  it('should not show toast when action is not rejected', async () => {
+  it('should not handle error when action is not rejected', async () => {
     const action = {
       type: 'action/loading',
       payload: null,
@@ -50,11 +70,14 @@ describe('errorMiddlewareListener', () => {
         requestStatus: 'fulfilled',
       },
     };
-    await errorMiddlewareListener(action);
-    expect(showToast).not.toHaveBeenCalled();
+    const { getState, dispatch } = store;
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-expect-error
+    await errorMiddlewareListener(action, { getState, dispatch });
+    expect(dispatchSpy).not.toHaveBeenCalled();
   });
 
-  it('should show toast with unknown error when action payload is not a string', async () => {
+  it('should handle error with unknown error message when action payload is not a string', async () => {
     const action = {
       type: 'action/rejected',
       payload: {},
@@ -63,15 +86,24 @@ describe('errorMiddlewareListener', () => {
         rejectedWithValue: true,
         requestStatus: 'rejected',
       },
+      error: {
+        code: 'ERROR',
+        message: 'Error message',
+      },
     };
-    await errorMiddlewareListener(action);
-    expect(showToast).toHaveBeenCalledWith({
-      type: 'error',
-      message: 'An unknown error occurred. Please try again later.',
-    });
+    const { getState, dispatch } = store;
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-expect-error
+    await errorMiddlewareListener(action, { getState, dispatch });
+    expect(dispatchSpy).toHaveBeenCalledWith(
+      expect.objectContaining({
+        type: 'modal/openErrorReportModal',
+        payload: expect.anything(),
+      }),
+    );
   });
 
-  it('should show toast with custom message when action payload is a string', async () => {
+  it('should handle error with custom message when action payload is a string', async () => {
     const action = {
       type: 'action/rejected',
       payload: 'Failed to fetch',
@@ -80,8 +112,46 @@ describe('errorMiddlewareListener', () => {
         rejectedWithValue: true,
         requestStatus: 'rejected',
       },
+      error: {
+        code: 'ERROR',
+        message: 'xyz',
+        stack: 'stack',
+      },
+    };
+    const { getState, dispatch } = store;
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-expect-error
+    await errorMiddlewareListener(action, { getState, dispatch });
+    expect(dispatchSpy).toHaveBeenCalledWith(
+      expect.objectContaining({
+        type: 'modal/openErrorReportModal',
+        payload: expect.objectContaining({
+          stacktrace: 'stack',
+        }),
+      }),
+    );
+  });
+
+  it('should toast on access denied', async () => {
+    const action = {
+      type: 'action/rejected',
+      payload: null,
+      meta: {
+        requestId: '421',
+        rejectedWithValue: true,
+        requestStatus: 'rejected',
+      },
+      error: {
+        code: '403',
+      },
     };
-    await errorMiddlewareListener(action);
-    expect(showToast).toHaveBeenCalledWith({ type: 'error', message: 'Failed to fetch' });
+    const { getState, dispatch } = store;
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-expect-error
+    await errorMiddlewareListener(action, { getState, dispatch });
+    expect(showToast).toHaveBeenCalledWith({
+      message: 'Access denied.',
+      type: 'error',
+    });
   });
 });
diff --git a/src/redux/middlewares/error.middleware.ts b/src/redux/middlewares/error.middleware.ts
index 0ba6a0f75452822908c449ba4d3dcb0ac59dddd9..8c6bd8160be1d71fd632d1ec542b66c48c9017fc 100644
--- a/src/redux/middlewares/error.middleware.ts
+++ b/src/redux/middlewares/error.middleware.ts
@@ -1,30 +1,27 @@
-import type { AppStartListening } from '@/redux/store';
-import { UNKNOWN_ERROR } from '@/utils/getErrorMessage/getErrorMessage.constants';
+import type { AppListenerEffectAPI, AppStartListening } from '@/redux/store';
+import { Action, createListenerMiddleware, isRejected } from '@reduxjs/toolkit';
+import { createErrorData } from '@/utils/error-report/errorReporting';
+import { openErrorReportModal } from '@/redux/modal/modal.slice';
 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;
+export const errorMiddlewareListener = async (
+  action: Action,
+  { getState, dispatch }: AppListenerEffectAPI,
+): Promise<void> => {
+  if (isRejected(action) && action.type !== 'user/getSessionValid/rejected') {
+    if (action.error.code === '403') {
+      showToast({
+        type: 'error',
+        message: 'Access denied.',
+      });
     } else {
-      message = UNKNOWN_ERROR;
+      const errorData = await createErrorData(action.error, getState());
+      dispatch(openErrorReportModal(errorData));
     }
-
-    showToast({
-      type: 'error',
-      message,
-    });
   }
 };
 
diff --git a/src/redux/modal/modal.constants.ts b/src/redux/modal/modal.constants.ts
index f0df9964801af60a083ceb6a773b4a7c8375c40f..d7dea45c423398a99180fcd4151255ad93489fdf 100644
--- a/src/redux/modal/modal.constants.ts
+++ b/src/redux/modal/modal.constants.ts
@@ -12,4 +12,5 @@ export const MODAL_INITIAL_STATE: ModalState = {
     uniprotId: MOL_ART_UNIPROT_ID_DEFAULT,
   },
   editOverlayState: null,
+  errorReportState: {},
 };
diff --git a/src/redux/modal/modal.mock.ts b/src/redux/modal/modal.mock.ts
index 22b833031510bdea484a479d1fc43faa52c66c74..cde5fab5cc156a2783af5987006fc87e499f7477 100644
--- a/src/redux/modal/modal.mock.ts
+++ b/src/redux/modal/modal.mock.ts
@@ -12,4 +12,5 @@ export const MODAL_INITIAL_STATE_MOCK: ModalState = {
     uniprotId: MOL_ART_UNIPROT_ID_DEFAULT,
   },
   editOverlayState: null,
+  errorReportState: {},
 };
diff --git a/src/redux/modal/modal.reducers.ts b/src/redux/modal/modal.reducers.ts
index 4871a245229a6dc20149d9599e86e2258a1eb087..24ae505605ac7a2d4ed377f2069d4aa918e6baf9 100644
--- a/src/redux/modal/modal.reducers.ts
+++ b/src/redux/modal/modal.reducers.ts
@@ -1,5 +1,6 @@
 import { ModalName } from '@/types/modal';
 import { PayloadAction } from '@reduxjs/toolkit';
+import { ErrorData } from '@/utils/error-report/ErrorData';
 import { ModalState, OpenEditOverlayModalAction } from './modal.types';
 
 export const openModalReducer = (state: ModalState, action: PayloadAction<ModalName>): void => {
@@ -48,6 +49,18 @@ export const openLoggedInMenuModalReducer = (state: ModalState): void => {
   state.modalTitle = 'Select';
 };
 
+export const openErrorReportModalReducer = (
+  state: ModalState,
+  action: PayloadAction<ErrorData | undefined>,
+): void => {
+  state.isOpen = true;
+  state.modalName = 'error-report';
+  state.modalTitle = 'An error occurred!';
+  state.errorReportState = {
+    errorData: action.payload,
+  };
+};
+
 export const setOverviewImageIdReducer = (
   state: ModalState,
   action: PayloadAction<number>,
diff --git a/src/redux/modal/modal.selector.ts b/src/redux/modal/modal.selector.ts
index c77223ea30f739d335170d382c9ecb524b6b6a49..654dfb7aeac4b0b43a89cb676a92b9bf7d09922d 100644
--- a/src/redux/modal/modal.selector.ts
+++ b/src/redux/modal/modal.selector.ts
@@ -20,3 +20,8 @@ export const currentEditedOverlaySelector = createSelector(
   modalSelector,
   modal => modal.editOverlayState,
 );
+
+export const currentErrorDataSelector = createSelector(
+  modalSelector,
+  modal => modal?.errorReportState.errorData || undefined,
+);
diff --git a/src/redux/modal/modal.slice.ts b/src/redux/modal/modal.slice.ts
index c1fe7b36a49f38f8ed81fbf0a2c32a01b54ceb76..40f7ed6566b9b89c6127e67effb65b5daff38b9d 100644
--- a/src/redux/modal/modal.slice.ts
+++ b/src/redux/modal/modal.slice.ts
@@ -10,6 +10,7 @@ import {
   openPublicationsModalReducer,
   openEditOverlayModalReducer,
   openLoggedInMenuModalReducer,
+  openErrorReportModalReducer,
 } from './modal.reducers';
 
 const modalSlice = createSlice({
@@ -25,6 +26,7 @@ const modalSlice = createSlice({
     openPublicationsModal: openPublicationsModalReducer,
     openEditOverlayModal: openEditOverlayModalReducer,
     openLoggedInMenuModal: openLoggedInMenuModalReducer,
+    openErrorReportModal: openErrorReportModalReducer,
   },
 });
 
@@ -38,6 +40,7 @@ export const {
   openPublicationsModal,
   openEditOverlayModal,
   openLoggedInMenuModal,
+  openErrorReportModal,
 } = modalSlice.actions;
 
 export default modalSlice.reducer;
diff --git a/src/redux/modal/modal.types.ts b/src/redux/modal/modal.types.ts
index dfb5ca5d5c5a1f7b020b766bed4b7602e9cc2526..ea77209610093378c152d5d114f41bc475bd97fb 100644
--- a/src/redux/modal/modal.types.ts
+++ b/src/redux/modal/modal.types.ts
@@ -1,6 +1,7 @@
 import { ModalName } from '@/types/modal';
 import { MapOverlay } from '@/types/models';
 import { PayloadAction } from '@reduxjs/toolkit';
+import { ErrorData } from '@/utils/error-report/ErrorData';
 
 export type OverviewImagesModalState = {
   imageId?: number;
@@ -10,6 +11,10 @@ export type MolArtModalState = {
   uniprotId?: string | undefined;
 };
 
+export type ErrorRepostState = {
+  errorData?: ErrorData | undefined;
+};
+
 export type EditOverlayState = MapOverlay | null;
 
 export interface ModalState {
@@ -18,6 +23,7 @@ export interface ModalState {
   modalTitle: string;
   overviewImagesState: OverviewImagesModalState;
   molArtState: MolArtModalState;
+  errorReportState: ErrorRepostState;
   editOverlayState: EditOverlayState;
 }
 
diff --git a/src/redux/models/models.reducers.test.ts b/src/redux/models/models.reducers.test.ts
index fc6e0af1e28e47a3bb0e2ed3a38186549c053907..c25cd72d4bff9e4510cbb0b6b596201c13831ec1 100644
--- a/src/redux/models/models.reducers.test.ts
+++ b/src/redux/models/models.reducers.test.ts
@@ -6,6 +6,7 @@ import {
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import modelsReducer from './models.slice';
 import { getModels } from './models.thunks';
 import { ModelsState } from './models.types';
@@ -44,11 +45,11 @@ describe('models reducer', () => {
   it('should update store after failed getModels query', async () => {
     mockedAxiosClient.onGet(apiPath.getModelsString()).reply(HttpStatusCode.NotFound, []);
 
-    const { type, payload } = await store.dispatch(getModels());
+    const action = await store.dispatch(getModels());
     const { data, loading, error } = store.getState().models;
 
-    expect(type).toBe('project/getModels/rejected');
-    expect(payload).toBe(
+    expect(action.type).toBe('project/getModels/rejected');
+    expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch models: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
     expect(loading).toEqual('failed');
diff --git a/src/redux/models/models.thunks.ts b/src/redux/models/models.thunks.ts
index 2e0fd68d89e09cff7b66e6c5e1aefff3acc15486..d81096c9dd853bf571c31de25006583c1b60c36a 100644
--- a/src/redux/models/models.thunks.ts
+++ b/src/redux/models/models.thunks.ts
@@ -2,16 +2,16 @@ 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 { getError } from '@/utils/error-report/getError';
 import { MODELS_FETCHING_ERROR_PREFIX } from './models.constants';
 
 export const getModels = createAsyncThunk<MapModel[] | undefined, void, ThunkConfig>(
   'project/getModels',
-  async (_, { rejectWithValue }) => {
+  async () => {
     try {
       const response = await axiosInstance.get<MapModel[]>(apiPath.getModelsString());
 
@@ -19,9 +19,7 @@ export const getModels = createAsyncThunk<MapModel[] | undefined, void, ThunkCon
 
       return isDataValid ? response.data : undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: MODELS_FETCHING_ERROR_PREFIX });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: MODELS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts b/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts
index 956b6751b59b785cf082e89b5630f65d8acaf08f..f726bd8fff76200318f7e4f0b40c64bfb985eb3e 100644
--- a/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts
+++ b/src/redux/overlayBioEntity/overlayBioEntity.thunk.ts
@@ -3,8 +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 { getError } from '@/utils/error-report/getError';
 import {
   getValidOverlayBioEntities,
   parseOverlayBioEntityToOlRenderingFormat,
@@ -30,7 +30,7 @@ export const getOverlayBioEntity = createAsyncThunk<
   OverlayBioEntityRender[] | undefined,
   GetOverlayBioEntityThunkProps,
   ThunkConfig
->('overlayBioEntity/getOverlayBioEntity', async ({ overlayId, modelId }, { rejectWithValue }) => {
+>('overlayBioEntity/getOverlayBioEntity', async ({ overlayId, modelId }) => {
   try {
     const response = await axiosInstanceNewAPI.get<OverlayBioEntity[]>(
       apiPath.getOverlayBioEntity({ overlayId, modelId }),
@@ -47,12 +47,7 @@ export const getOverlayBioEntity = createAsyncThunk<
 
     return undefined;
   } catch (error) {
-    const errorMessage = getErrorMessage({
-      error,
-      prefix: OVERLAY_BIO_ENTITY_FETCHING_ERROR_PREFIX,
-    });
-
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: OVERLAY_BIO_ENTITY_FETCHING_ERROR_PREFIX }));
   }
 });
 
@@ -65,7 +60,7 @@ export const getOverlayBioEntityForAllModels = createAsyncThunk<
 >(
   'overlayBioEntity/getOverlayBioEntityForAllModels',
   // eslint-disable-next-line consistent-return
-  async ({ overlayId }, { dispatch, getState, rejectWithValue }) => {
+  async ({ overlayId }, { dispatch, getState }) => {
     try {
       const state = getState();
       const modelsIds = modelsIdsSelector(state);
@@ -76,12 +71,9 @@ export const getOverlayBioEntityForAllModels = createAsyncThunk<
 
       await Promise.all(asyncGetOverlayBioEntityFunctions);
     } catch (error) {
-      const errorMessage = getErrorMessage({
-        error,
-        prefix: OVERLAY_BIO_ENTITY_ALL_MODELS_FETCHING_ERROR_PREFIX,
-      });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(
+        getError({ error, prefix: OVERLAY_BIO_ENTITY_ALL_MODELS_FETCHING_ERROR_PREFIX }),
+      );
     }
   },
 );
@@ -93,7 +85,7 @@ export const getInitOverlays = createAsyncThunk<
   GetInitOverlaysProps,
   { state: RootState } & ThunkConfig
   // eslint-disable-next-line consistent-return
->('appInit/getInitOverlays', async ({ overlaysId }, { dispatch, getState, rejectWithValue }) => {
+>('appInit/getInitOverlays', async ({ overlaysId }, { dispatch, getState }) => {
   try {
     const state = getState();
 
@@ -114,8 +106,6 @@ export const getInitOverlays = createAsyncThunk<
       dispatch(getOverlayBioEntityForAllModels({ overlayId: id }));
     });
   } catch (error) {
-    const errorMessage = getErrorMessage({ error, prefix: INIT_OVERLAYS_ERROR_PREFIX });
-
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: INIT_OVERLAYS_ERROR_PREFIX }));
   }
 });
diff --git a/src/redux/overlays/overlays.reducers.test.ts b/src/redux/overlays/overlays.reducers.test.ts
index 38b4652f0f0c29e09c3917d9de1160f9dc27fc4a..1c4cada35a94834d7b670696893c106d237f9106 100644
--- a/src/redux/overlays/overlays.reducers.test.ts
+++ b/src/redux/overlays/overlays.reducers.test.ts
@@ -14,6 +14,7 @@ import {
 import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
 import { waitFor } from '@testing-library/react';
+import { unwrapResult } from '@reduxjs/toolkit';
 import { apiPath } from '../apiPath';
 import overlaysReducer from './overlays.slice';
 import {
@@ -80,11 +81,11 @@ describe('overlays reducer', () => {
       .onGet(apiPath.getAllOverlaysByProjectIdQuery(PROJECT_ID, { publicOverlay: true }))
       .reply(HttpStatusCode.NotFound, []);
 
-    const { type, payload } = await store.dispatch(getAllPublicOverlaysByProjectId(PROJECT_ID));
+    const action = await store.dispatch(getAllPublicOverlaysByProjectId(PROJECT_ID));
     const { data, loading, error } = store.getState().overlays;
 
-    expect(type).toBe('overlays/getAllPublicOverlaysByProjectId/rejected');
-    expect(payload).toBe(
+    expect(action.type).toBe('overlays/getAllPublicOverlaysByProjectId/rejected');
+    expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch overlays: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
     expect(loading).toEqual('failed');
diff --git a/src/redux/overlays/overlays.thunks.ts b/src/redux/overlays/overlays.thunks.ts
index 67fd7b7d20e59979c665bccb5e5977fbd58f2ade..700eeb58024c66facd3888536301f49959165498 100644
--- a/src/redux/overlays/overlays.thunks.ts
+++ b/src/redux/overlays/overlays.thunks.ts
@@ -12,9 +12,9 @@ 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 { BASE_API_URL } from '@/constants';
+import { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import {
   CHUNK_SIZE,
@@ -32,7 +32,7 @@ import type { RootState } from '../store';
 
 export const getAllPublicOverlaysByProjectId = createAsyncThunk<MapOverlay[], string, ThunkConfig>(
   'overlays/getAllPublicOverlaysByProjectId',
-  async (projectId: string, { rejectWithValue }) => {
+  async (projectId: string) => {
     try {
       const response = await axiosInstance.get<MapOverlay[]>(
         apiPath.getAllOverlaysByProjectIdQuery(projectId, { publicOverlay: true }),
@@ -42,16 +42,14 @@ export const getAllPublicOverlaysByProjectId = createAsyncThunk<MapOverlay[], st
 
       return isDataValid ? response.data : [];
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: OVERLAYS_FETCHING_ERROR_PREFIX });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: OVERLAYS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
 
 export const getAllUserOverlaysByCreator = createAsyncThunk<MapOverlay[], void, ThunkConfig>(
   'overlays/getAllUserOverlaysByCreator',
-  async (_, { getState, rejectWithValue }) => {
+  async (_, { getState }) => {
     try {
       const state = getState() as RootState;
       const creator = state.user.login;
@@ -78,8 +76,7 @@ export const getAllUserOverlaysByCreator = createAsyncThunk<MapOverlay[], void,
 
       return isDataValid ? sortedUserOverlays : [];
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: USER_OVERLAYS_FETCHING_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: USER_OVERLAYS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
@@ -197,7 +194,7 @@ export const addOverlay = createAsyncThunk<undefined, AddOverlayArgs, ThunkConfi
   'overlays/addOverlay',
   async (
     { filename, content, description, name, type, projectId },
-    { rejectWithValue, dispatch },
+    { dispatch },
     // eslint-disable-next-line consistent-return
   ) => {
     try {
@@ -223,8 +220,7 @@ export const addOverlay = createAsyncThunk<undefined, AddOverlayArgs, ThunkConfi
 
       showToast({ type: 'success', message: USER_OVERLAY_ADD_SUCCESS_MESSAGE });
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: USER_OVERLAY_ADD_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: USER_OVERLAY_ADD_ERROR_PREFIX }));
     }
   },
 );
@@ -232,7 +228,7 @@ export const addOverlay = createAsyncThunk<undefined, AddOverlayArgs, ThunkConfi
 export const updateOverlays = createAsyncThunk<undefined, MapOverlay[], ThunkConfig>(
   'overlays/updateOverlays',
   // eslint-disable-next-line consistent-return
-  async (userOverlays, { rejectWithValue }) => {
+  async userOverlays => {
     try {
       const userOverlaysPromises = userOverlays.map(userOverlay =>
         axiosInstance.patch<MapOverlay>(
@@ -256,9 +252,7 @@ export const updateOverlays = createAsyncThunk<undefined, MapOverlay[], ThunkCon
 
       showToast({ type: 'success', message: USER_OVERLAY_UPDATE_SUCCESS_MESSAGE });
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: USER_OVERLAY_UPDATE_ERROR_PREFIX });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: USER_OVERLAY_UPDATE_ERROR_PREFIX }));
     }
   },
 );
@@ -266,7 +260,7 @@ export const updateOverlays = createAsyncThunk<undefined, MapOverlay[], ThunkCon
 export const removeOverlay = createAsyncThunk<undefined, { overlayId: number }, ThunkConfig>(
   'overlays/removeOverlay',
   // eslint-disable-next-line consistent-return
-  async ({ overlayId }, { dispatch, rejectWithValue }) => {
+  async ({ overlayId }, { dispatch }) => {
     try {
       await axiosInstance.delete(apiPath.removeOverlay(overlayId), {
         withCredentials: true,
@@ -278,8 +272,7 @@ export const removeOverlay = createAsyncThunk<undefined, { overlayId: number },
 
       showToast({ type: 'success', message: USER_OVERLAY_REMOVE_SUCCESS_MESSAGE });
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: USER_OVERLAY_REMOVE_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: USER_OVERLAY_REMOVE_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/plugins/plugins.reducers.test.ts b/src/redux/plugins/plugins.reducers.test.ts
index ecbedd35721534bef5f6d274192873088206a28f..d5a7f0103f696eb9654a7edb482114fd2dbc4c42 100644
--- a/src/redux/plugins/plugins.reducers.test.ts
+++ b/src/redux/plugins/plugins.reducers.test.ts
@@ -6,6 +6,7 @@ import {
 import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
 import { pluginFixture } from '@/models/fixtures/pluginFixture';
+import { unwrapResult } from '@reduxjs/toolkit';
 import { apiPath } from '../apiPath';
 import { PluginsState } from './plugins.types';
 import pluginsReducer, { removePlugin } from './plugins.slice';
@@ -59,7 +60,7 @@ describe('plugins reducer', () => {
   it('should update store after failed registerPlugin query', async () => {
     mockedAxiosClient.onPost(apiPath.registerPluign()).reply(HttpStatusCode.NotFound, undefined);
 
-    const { type, payload } = await store.dispatch(
+    const action = await store.dispatch(
       registerPlugin({
         hash: pluginFixture.hash,
         isPublic: pluginFixture.isPublic,
@@ -70,8 +71,8 @@ describe('plugins reducer', () => {
       }),
     );
 
-    expect(type).toBe('plugins/registerPlugin/rejected');
-    expect(payload).toEqual(
+    expect(action.type).toBe('plugins/registerPlugin/rejected');
+    expect(() => unwrapResult(action)).toThrow(
       "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;
diff --git a/src/redux/plugins/plugins.thunks.ts b/src/redux/plugins/plugins.thunks.ts
index 9f2108c4973f882ae17268ea73d2ca0e11da30c9..19dd2592d828443d2dd5ff52e41147d3ccc231a8 100644
--- a/src/redux/plugins/plugins.thunks.ts
+++ b/src/redux/plugins/plugins.thunks.ts
@@ -6,9 +6,9 @@ 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 { getPluginHashWithoutPrefix } from '@/utils/plugins/getPluginHashWithoutPrefix';
+import { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import {
   PLUGIN_FETCHING_ALL_ERROR_PREFIX,
@@ -31,10 +31,7 @@ export const registerPlugin = createAsyncThunk<
   ThunkConfig
 >(
   'plugins/registerPlugin',
-  async (
-    { hash, isPublic, pluginName, pluginUrl, pluginVersion, extendedPluginName },
-    { rejectWithValue },
-  ) => {
+  async ({ hash, isPublic, pluginName, pluginUrl, pluginVersion, extendedPluginName }) => {
     try {
       const hashWihtoutPrefix = getPluginHashWithoutPrefix(hash);
 
@@ -66,8 +63,7 @@ export const registerPlugin = createAsyncThunk<
 
       return undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: PLUGIN_REGISTER_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: PLUGIN_REGISTER_ERROR_PREFIX }));
     }
   },
 );
@@ -86,7 +82,7 @@ type GetInitPluginsProps = {
 export const getInitPlugins = createAsyncThunk<void, GetInitPluginsProps, ThunkConfig>(
   'plugins/getInitPlugins',
   // eslint-disable-next-line consistent-return
-  async ({ pluginsId, setHashedPlugin }, { rejectWithValue }) => {
+  async ({ pluginsId, setHashedPlugin }) => {
     try {
       /* eslint-disable no-restricted-syntax, no-await-in-loop */
 
@@ -112,15 +108,14 @@ export const getInitPlugins = createAsyncThunk<void, GetInitPluginsProps, ThunkC
         }
       }
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: PLUGIN_INIT_FETCHING_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: PLUGIN_INIT_FETCHING_ERROR_PREFIX }));
     }
   },
 );
 
 export const getAllPlugins = createAsyncThunk<MinervaPlugin[], void, ThunkConfig>(
   'plugins/getAllPlugins',
-  async (_, { rejectWithValue }) => {
+  async () => {
     try {
       const response = await axiosInstance.get<MinervaPlugin[]>(apiPath.getAllPlugins());
 
@@ -130,8 +125,7 @@ export const getAllPlugins = createAsyncThunk<MinervaPlugin[], void, ThunkConfig
 
       return validPlugins;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: PLUGIN_FETCHING_ALL_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: PLUGIN_FETCHING_ALL_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/project/project.reducers.test.ts b/src/redux/project/project.reducers.test.ts
index 0521d9c262092e38956e8d239c5a8b82fb337610..6579fe788be4eb12bbebb7284648bf35b065925d 100644
--- a/src/redux/project/project.reducers.test.ts
+++ b/src/redux/project/project.reducers.test.ts
@@ -6,6 +6,7 @@ import {
 } from '@/utils/createStoreInstanceUsingSliceReducer';
 import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
+import { unwrapResult } from '@reduxjs/toolkit';
 import { apiPath } from '../apiPath';
 import projectReducer from './project.slice';
 import { getProjectById } from './project.thunks';
@@ -48,11 +49,11 @@ describe('project reducer', () => {
   it('should update store after failed getProjectById query', async () => {
     mockedAxiosClient.onGet(apiPath.getProjectById(PROJECT_ID)).reply(HttpStatusCode.NotFound, []);
 
-    const { type, payload } = await store.dispatch(getProjectById(PROJECT_ID));
+    const action = await store.dispatch(getProjectById(PROJECT_ID));
     const { data, loading, error } = store.getState().project;
 
-    expect(type).toBe('project/getProjectById/rejected');
-    expect(payload).toBe(
+    expect(action.type).toBe('project/getProjectById/rejected');
+    expect(() => unwrapResult(action)).toThrow(
       "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');
diff --git a/src/redux/project/project.thunks.ts b/src/redux/project/project.thunks.ts
index 23a73a0934aae9f5351d7810beb40666d93f9076..21d990741207aa2beea8d5cfab79a561fb47b1a8 100644
--- a/src/redux/project/project.thunks.ts
+++ b/src/redux/project/project.thunks.ts
@@ -3,16 +3,16 @@ 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 { DEFAULT_PROJECT_ID } from '@/constants';
+import { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import { PROJECT_FETCHING_ERROR_PREFIX } from './project.constants';
 import { SetProjectIdParams } from './project.types';
 
 export const getProjectById = createAsyncThunk<Project | undefined, string, ThunkConfig>(
   'project/getProjectById',
-  async (id, { rejectWithValue }) => {
+  async id => {
     try {
       const response = await axiosInstanceNewAPI.get<Project>(apiPath.getProjectById(id));
 
@@ -20,8 +20,7 @@ export const getProjectById = createAsyncThunk<Project | undefined, string, Thun
 
       return isDataValid ? response.data : undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: PROJECT_FETCHING_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: PROJECT_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/publications/publications.thunks.ts b/src/redux/publications/publications.thunks.ts
index f50b611eec013b7e09a0b9773775f6fafc9e4cba..4c03def9f0b594ea9450d5733df8034d7bc8cce7 100644
--- a/src/redux/publications/publications.thunks.ts
+++ b/src/redux/publications/publications.thunks.ts
@@ -3,8 +3,8 @@ 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 { getError } from '@/utils/error-report/getError';
 import { GetPublicationsParams } from './publications.types';
 import { apiPath } from '../apiPath';
 import { PUBLICATIONS_FETCHING_ERROR_PREFIX } from './publications.constatns';
@@ -13,7 +13,7 @@ export const getPublications = createAsyncThunk<
   PublicationsResponse | undefined,
   GetPublicationsParams,
   ThunkConfig
->('publications/getPublications', async (params, { rejectWithValue }) => {
+>('publications/getPublications', async params => {
   try {
     const response = await axiosInstance.get<PublicationsResponse>(apiPath.getPublications(params));
 
@@ -21,7 +21,6 @@ export const getPublications = createAsyncThunk<
 
     return isDataValid ? response.data : undefined;
   } catch (error) {
-    const errorMessage = getErrorMessage({ error, prefix: PUBLICATIONS_FETCHING_ERROR_PREFIX });
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: PUBLICATIONS_FETCHING_ERROR_PREFIX }));
   }
 });
diff --git a/src/redux/reactions/reactions.thunks.ts b/src/redux/reactions/reactions.thunks.ts
index 610a83adfced0672fe526d609df7072842e3c264..5a650ebce706d23eecad1e8c1fdd72a95b2411d2 100644
--- a/src/redux/reactions/reactions.thunks.ts
+++ b/src/redux/reactions/reactions.thunks.ts
@@ -3,10 +3,10 @@ import { apiPath } from '@/redux/apiPath';
 import { axiosInstance } from '@/services/api/utils/axiosInstance';
 import { Reaction } from '@/types/models';
 import { ThunkConfig } from '@/types/store';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { z } from 'zod';
+import { getError } from '@/utils/error-report/getError';
 import { REACTIONS_FETCHING_ERROR_PREFIX } from './reactions.constants';
 
 type GetReactionsByIdsArgs =
@@ -25,7 +25,7 @@ export const getReactionsByIds = createAsyncThunk<
   GetReactionsByIdsResult | undefined,
   GetReactionsByIdsArgs,
   ThunkConfig
->('reactions/getByIds', async (args, { rejectWithValue }) => {
+>('reactions/getByIds', async args => {
   const ids = args instanceof Array ? args : args.ids;
   const shouldConcat = args instanceof Array ? false : args.shouldConcat || false;
 
@@ -42,7 +42,6 @@ export const getReactionsByIds = createAsyncThunk<
       shouldConcat,
     };
   } catch (error) {
-    const errorMessage = getErrorMessage({ error, prefix: REACTIONS_FETCHING_ERROR_PREFIX });
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: REACTIONS_FETCHING_ERROR_PREFIX }));
   }
 });
diff --git a/src/redux/search/search.thunks.ts b/src/redux/search/search.thunks.ts
index da0607cd0fc7a73500a42821a574cd65e13cdd9d..5d1e36e8b7c5c7a818be6981636a9935c0ee1680 100644
--- a/src/redux/search/search.thunks.ts
+++ b/src/redux/search/search.thunks.ts
@@ -3,8 +3,8 @@ import { getMultiChemicals } from '@/redux/chemicals/chemicals.thunks';
 import { getMultiDrugs } from '@/redux/drugs/drugs.thunks';
 import { PerfectMultiSearchParams } from '@/types/search';
 import { ThunkConfig } from '@/types/store';
-import { getErrorMessage } from '@/utils/getErrorMessage';
 import { createAsyncThunk } from '@reduxjs/toolkit';
+import { getError } from '@/utils/error-report/getError';
 import { resetReactionsData } from '../reactions/reactions.slice';
 import type { RootState } from '../store';
 import { DATA_SEARCHING_ERROR_PREFIX } from './search.constants';
@@ -20,7 +20,7 @@ export const getSearchData = createAsyncThunk<
 >(
   'project/getSearchData',
   // eslint-disable-next-line consistent-return
-  async ({ searchQueries, isPerfectMatch }, { dispatch, getState, rejectWithValue }) => {
+  async ({ searchQueries, isPerfectMatch }, { dispatch, getState }) => {
     try {
       dispatch(resetReactionsData());
 
@@ -46,9 +46,7 @@ export const getSearchData = createAsyncThunk<
 
       dispatchPluginsEvents(searchQueries, getState());
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: DATA_SEARCHING_ERROR_PREFIX });
-
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: DATA_SEARCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/statistics/statistics.reducers.test.ts b/src/redux/statistics/statistics.reducers.test.ts
index 6d620db1720db9fa9f929ed84fe94c1cb32d8b0c..45a0b8430eb9cca2df2a7eae9fcb08c5487cd4a6 100644
--- a/src/redux/statistics/statistics.reducers.test.ts
+++ b/src/redux/statistics/statistics.reducers.test.ts
@@ -7,6 +7,7 @@ import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
 import { waitFor } from '@testing-library/react';
 import { statisticsFixture } from '@/models/fixtures/statisticsFixture';
+import { unwrapResult } from '@reduxjs/toolkit';
 import { StatisticsState } from './statistics.types';
 import statisticsReducer from './statistics.slice';
 import { apiPath } from '../apiPath';
@@ -56,11 +57,12 @@ describe('statistics reducer', () => {
       .onGet(apiPath.getStatisticsById(PROJECT_ID))
       .reply(HttpStatusCode.NotFound, undefined);
 
-    const { type, payload } = await store.dispatch(getStatisticsById(PROJECT_ID));
+    const action = await store.dispatch(getStatisticsById(PROJECT_ID));
+
     const { loading } = store.getState().statistics;
 
-    expect(type).toBe('statistics/getStatisticsById/rejected');
-    expect(payload).toBe(
+    expect(action.type).toBe('statistics/getStatisticsById/rejected');
+    expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch statistics: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
 
diff --git a/src/redux/statistics/statistics.thunks.ts b/src/redux/statistics/statistics.thunks.ts
index 1a683a4e3ea3e50238f1fce85b47dbde93b59b98..dcaf0100818bce4c9d6a5c90f5698fc11adcbfa7 100644
--- a/src/redux/statistics/statistics.thunks.ts
+++ b/src/redux/statistics/statistics.thunks.ts
@@ -3,14 +3,14 @@ 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 { getError } from '@/utils/error-report/getError';
 import { apiPath } from '../apiPath';
 import { STATISTICS_FETCHING_ERROR_PREFIX } from './statistics.constants';
 
 export const getStatisticsById = createAsyncThunk<Statistics | undefined, string, ThunkConfig>(
   'statistics/getStatisticsById',
-  async (id, { rejectWithValue }) => {
+  async id => {
     try {
       const response = await axiosInstance.get<Statistics>(apiPath.getStatisticsById(id));
 
@@ -18,8 +18,7 @@ export const getStatisticsById = createAsyncThunk<Statistics | undefined, string
 
       return isDataValid ? response.data : undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({ error, prefix: STATISTICS_FETCHING_ERROR_PREFIX });
-      return rejectWithValue(errorMessage);
+      return Promise.reject(getError({ error, prefix: STATISTICS_FETCHING_ERROR_PREFIX }));
     }
   },
 );
diff --git a/src/redux/user/user.mock.ts b/src/redux/user/user.mock.ts
index 5d372ee070a0d3d282ade62cfaba0972cef2d462..ac2813cfdadb09548212b8b0f0dd5e80bef14511 100644
--- a/src/redux/user/user.mock.ts
+++ b/src/redux/user/user.mock.ts
@@ -6,4 +6,5 @@ export const USER_INITIAL_STATE_MOCK: UserState = {
   error: { name: '', message: '' },
   login: null,
   role: null,
+  userData: null,
 };
diff --git a/src/redux/user/user.reducers.test.ts b/src/redux/user/user.reducers.test.ts
index 9d0fd4093fb3bbf2619528c8be7bb8fb63756116..3033a51affb22201af934a6d97121115644077b9 100644
--- a/src/redux/user/user.reducers.test.ts
+++ b/src/redux/user/user.reducers.test.ts
@@ -8,7 +8,7 @@ import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
 import { HttpStatusCode } from 'axios';
 import { loginFixture } from '@/models/fixtures/loginFixture';
 import { sessionFixture } from '@/models/fixtures/sessionFixture';
-import { userPrivilegesFixture } from '@/models/fixtures/userPrivilegesFixture';
+import { userFixture } from '@/models/fixtures/userFixture';
 import { apiPath } from '../apiPath';
 import userReducer from './user.slice';
 
@@ -25,6 +25,7 @@ const INITIAL_STATE: UserState = {
   error: { name: '', message: '' },
   login: null,
   role: null,
+  userData: null,
 };
 
 describe('user reducer', () => {
@@ -40,9 +41,7 @@ describe('user reducer', () => {
 
   it('should update store after successful login query', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
-    mockedAxiosClient
-      .onGet(apiPath.userPrivileges(loginFixture.login))
-      .reply(HttpStatusCode.Ok, userPrivilegesFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
     await store.dispatch(login(CREDENTIALS));
     const { authenticated, loading } = store.getState().user;
 
@@ -52,6 +51,7 @@ describe('user reducer', () => {
 
   it('should update store on loading login query', async () => {
     mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
     const loginPromise = store.dispatch(login(CREDENTIALS));
 
     const { authenticated, loading } = store.getState().user;
@@ -63,21 +63,26 @@ describe('user reducer', () => {
     const { authenticated: authenticatedFulfilled, loading: promiseFulfilled } =
       store.getState().user;
 
-    expect(authenticatedFulfilled).toBe(true);
     expect(promiseFulfilled).toEqual('succeeded');
+    expect(authenticatedFulfilled).toBe(true);
   });
 
   it('should update store after successful getSessionValid query', async () => {
     mockedAxiosClient.onGet(apiPath.getSessionValid()).reply(HttpStatusCode.Ok, sessionFixture);
     mockedAxiosClient
-      .onGet(apiPath.userPrivileges(sessionFixture.login))
-      .reply(HttpStatusCode.Ok, userPrivilegesFixture);
+      .onGet(apiPath.user(sessionFixture.login))
+      .reply(HttpStatusCode.Ok, userFixture);
+
+    mockedAxiosClient
+      .onGet(apiPath.user(sessionFixture.login))
+      .reply(HttpStatusCode.Ok, userFixture);
 
     await store.dispatch(getSessionValid());
-    const { authenticated, loading, login: sessionLogin } = store.getState().user;
+    const { authenticated, loading, login: sessionLogin, userData } = store.getState().user;
 
-    expect(authenticated).toBe(true);
     expect(loading).toEqual('succeeded');
+    expect(authenticated).toBe(true);
     expect(sessionLogin).toBeDefined();
+    expect(userData).toBeDefined();
   });
 });
diff --git a/src/redux/user/user.reducers.ts b/src/redux/user/user.reducers.ts
index 8bad6c7e195adf406eeba3b5d4e85d1afab82706..2cb2002a5ad810bd67698c60aaa5618ec3ab41b3 100644
--- a/src/redux/user/user.reducers.ts
+++ b/src/redux/user/user.reducers.ts
@@ -12,6 +12,7 @@ export const loginReducer = (builder: ActionReducerMapBuilder<UserState>): void
       state.loading = 'succeeded';
       state.role = action.payload?.role || null;
       state.login = action.payload?.login || null;
+      state.userData = action.payload?.userData || null;
     })
     .addCase(login.rejected, state => {
       state.authenticated = false;
@@ -29,6 +30,7 @@ export const getSessionValidReducer = (builder: ActionReducerMapBuilder<UserStat
       state.loading = 'succeeded';
       state.login = action.payload?.login || null;
       state.role = action.payload?.role || null;
+      state.userData = action.payload?.userData || null;
     })
     .addCase(getSessionValid.rejected, state => {
       state.authenticated = false;
@@ -47,6 +49,7 @@ export const logoutReducer = (builder: ActionReducerMapBuilder<UserState>): void
       state.loading = 'succeeded';
       state.role = null;
       state.login = null;
+      state.userData = null;
     })
     .addCase(logout.rejected, state => {
       state.loading = 'failed';
diff --git a/src/redux/user/user.slice.ts b/src/redux/user/user.slice.ts
index 325d9520aebe83d3c042829ae2e8e93bac9a6ce5..bf9f7f388be72f4f379e258fe78705dd60dcbcf3 100644
--- a/src/redux/user/user.slice.ts
+++ b/src/redux/user/user.slice.ts
@@ -8,6 +8,7 @@ export const initialState: UserState = {
   error: { name: '', message: '' },
   login: null,
   role: null,
+  userData: null,
 };
 
 export const userSlice = createSlice({
diff --git a/src/redux/user/user.thunks.test.ts b/src/redux/user/user.thunks.test.ts
index 982274d9bd4d6190f7eb3fb4f7196f2ff8b38d70..e0baefa9c8765d0ea64723c2e27ffb70f10387dd 100644
--- a/src/redux/user/user.thunks.test.ts
+++ b/src/redux/user/user.thunks.test.ts
@@ -5,12 +5,15 @@ import {
   ToolkitStoreWithSingleSlice,
   createStoreInstanceUsingSliceReducer,
 } from '@/utils/createStoreInstanceUsingSliceReducer';
+import { showToast } from '@/utils/showToast';
 import { apiPath } from '../apiPath';
 import { closeModal } from '../modal/modal.slice';
 import userReducer from './user.slice';
 import { UserState } from './user.types';
 import { login } from './user.thunks';
 
+jest.mock('../../utils/showToast');
+
 const mockedAxiosClient = mockNetworkResponse();
 const CREDENTIALS = {
   login: 'test',
@@ -50,4 +53,15 @@ describe('login thunk', () => {
 
     await store.dispatch(login(CREDENTIALS));
   });
+
+  it('dispatch showToast on failed login with invalid data', async () => {
+    mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Unauthorized, loginFixture);
+
+    await store.dispatch(login(CREDENTIALS));
+
+    expect(showToast).toHaveBeenCalledWith({
+      message: 'Invalid credentials.',
+      type: 'error',
+    });
+  });
 });
diff --git a/src/redux/user/user.thunks.ts b/src/redux/user/user.thunks.ts
index 5741e090ceaf830c7abc704a847becf95cee9668..6abb07c34200d96522c4c69c59586f950b44b160 100644
--- a/src/redux/user/user.thunks.ts
+++ b/src/redux/user/user.thunks.ts
@@ -3,22 +3,16 @@ import { createAsyncThunk } from '@reduxjs/toolkit';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { loginSchema } from '@/models/loginSchema';
 import { sessionSchemaValid } from '@/models/sessionValidSchema';
-import { Login, SessionValid, UserPrivileges } from '@/types/models';
-import { getErrorMessage } from '@/utils/getErrorMessage';
+import { Login, SessionValid, User, UserPrivilege } from '@/types/models';
 import { USER_ROLE } from '@/constants/user';
+import { getError } from '@/utils/error-report/getError';
+import axios, { HttpStatusCode } from 'axios';
+import { showToast } from '@/utils/showToast';
 import { apiPath } from '../apiPath';
 import { closeModal, openLoggedInMenuModal } from '../modal/modal.slice';
 import { hasPrivilege } from './user.utils';
 
-const getUserRole = async (login: string): Promise<string> => {
-  const response = await axiosInstance.get<UserPrivileges>(apiPath.userPrivileges(login), {
-    withCredentials: true,
-  });
-
-  const {
-    data: { privileges },
-  } = response;
-
+const getUserRole = (privileges: UserPrivilege[]): string => {
   if (hasPrivilege(privileges, 'IS_ADMIN')) {
     return USER_ROLE.ADMIN;
   }
@@ -29,9 +23,17 @@ const getUserRole = async (login: string): Promise<string> => {
   return USER_ROLE.USER;
 };
 
+const getUserData = async (login: string): Promise<User> => {
+  const response = await axiosInstance.get<User>(apiPath.user(login), {
+    withCredentials: true,
+  });
+
+  return response.data;
+};
+
 export const login = createAsyncThunk(
   'user/login',
-  async (credentials: { login: string; password: string }, { dispatch, rejectWithValue }) => {
+  async (credentials: { login: string; password: string }, { dispatch }) => {
     try {
       const searchParams = new URLSearchParams(credentials);
       const response = await axiosInstance.post<Login>(apiPath.postLogin(), searchParams, {
@@ -42,7 +44,8 @@ export const login = createAsyncThunk(
       const loginName = response.data.login;
 
       if (isDataValid) {
-        const role = await getUserRole(loginName);
+        const userData = await getUserData(loginName);
+        const role = getUserRole(userData.privileges);
 
         if (role !== USER_ROLE.ADMIN && role !== USER_ROLE.CURATOR) {
           dispatch(closeModal());
@@ -53,17 +56,22 @@ export const login = createAsyncThunk(
         return {
           login: loginName,
           role,
+          userData,
         };
       }
 
       return undefined;
     } catch (error) {
-      const errorMessage = getErrorMessage({
-        error,
-        prefix: 'Login',
-      });
-
-      return rejectWithValue(errorMessage);
+      if (axios.isAxiosError(error)) {
+        if (error?.response?.status === HttpStatusCode.Unauthorized) {
+          showToast({
+            type: 'error',
+            message: 'Invalid credentials.',
+          });
+          return undefined;
+        }
+      }
+      return Promise.reject(getError({ error, prefix: 'Login' }));
     }
   },
 );
@@ -79,11 +87,13 @@ export const getSessionValid = createAsyncThunk('user/getSessionValid', async ()
     data: { login: loginName },
   } = response;
 
-  const role = await getUserRole(loginName);
+  const userData = await getUserData(loginName);
+  const role = getUserRole(userData.privileges);
 
   if (isDataValid) {
     return {
       login: loginName,
+      userData,
       role,
     };
   }
@@ -91,7 +101,7 @@ export const getSessionValid = createAsyncThunk('user/getSessionValid', async ()
   return undefined;
 });
 
-export const logout = createAsyncThunk('user/logout', async (_, { rejectWithValue }) => {
+export const logout = createAsyncThunk('user/logout', async () => {
   try {
     await axiosInstance.post(apiPath.logout(), null, {
       withCredentials: true,
@@ -99,11 +109,6 @@ export const logout = createAsyncThunk('user/logout', async (_, { rejectWithValu
 
     return undefined;
   } catch (error) {
-    const errorMessage = getErrorMessage({
-      error,
-      prefix: 'Log out',
-    });
-
-    return rejectWithValue(errorMessage);
+    return Promise.reject(getError({ error, prefix: 'Log out' }));
   }
 });
diff --git a/src/redux/user/user.types.ts b/src/redux/user/user.types.ts
index 459a86e3861930f8892211fa05d3164a70ea4015..08210c0a3b06dbb700b583fcbf76073ecd838784 100644
--- a/src/redux/user/user.types.ts
+++ b/src/redux/user/user.types.ts
@@ -1,4 +1,5 @@
 import { Loading } from '@/types/loadingState';
+import { User } from '@/types/models';
 
 export type UserState = {
   loading: Loading;
@@ -6,4 +7,5 @@ export type UserState = {
   authenticated: boolean;
   login: null | string;
   role: string | null;
+  userData: User | null;
 };
diff --git a/src/redux/user/user.utils.ts b/src/redux/user/user.utils.ts
index 89a7afb8ae7e651dd682d7b9d0c2ff15c1cf8c87..ecb9c6239006f351b806b4fbf32d7bcf5cacd652 100644
--- a/src/redux/user/user.utils.ts
+++ b/src/redux/user/user.utils.ts
@@ -1,8 +1,5 @@
-import { UserPrivileges } from '@/types/models';
+import { UserPrivilege } from '@/types/models';
 
-export const hasPrivilege = (
-  privileges: UserPrivileges['privileges'],
-  privilegeType: string,
-): boolean => {
+export const hasPrivilege = (privileges: UserPrivilege[], privilegeType: string): boolean => {
   return privileges.some(privilege => privilege.privilegeType === privilegeType);
 };
diff --git a/src/shared/Input/Input.component.tsx b/src/shared/Input/Input.component.tsx
index 68cf9097dbb05b652a539d52cb0ccdefdc9901d1..00f3e9240109b21b66e54974b9676daf5ee8c11b 100644
--- a/src/shared/Input/Input.component.tsx
+++ b/src/shared/Input/Input.component.tsx
@@ -1,7 +1,7 @@
 import React, { InputHTMLAttributes } from 'react';
 import { twMerge } from 'tailwind-merge';
 
-type StyleVariant = 'primary';
+type StyleVariant = 'primary' | 'primaryWithoutFull';
 type SizeVariant = 'small' | 'medium';
 
 type InputProps = {
@@ -13,6 +13,8 @@ type InputProps = {
 const styleVariants = {
   primary:
     'w-full border border-transparent bg-cultured px-2 py-2.5 font-semibold outline-none hover:border-greyscale-600 focus:border-greyscale-600',
+  primaryWithoutFull:
+    'border border-transparent bg-cultured px-2 py-2.5 font-semibold outline-none hover:border-greyscale-600 focus:border-greyscale-600',
 } as const;
 
 const sizeVariants = {
diff --git a/src/types/modal.ts b/src/types/modal.ts
index b268bf17ab32baf80f7adda78c5770c0bc482578..865adda9bd489d0d216fdc7f93abc51b1bf36970 100644
--- a/src/types/modal.ts
+++ b/src/types/modal.ts
@@ -5,4 +5,5 @@ export type ModalName =
   | 'login'
   | 'publications'
   | 'edit-overlay'
+  | 'error-report'
   | 'logged-in-menu';
diff --git a/src/types/models.ts b/src/types/models.ts
index 0bebd142f8e74520ca349a519070a3555fdfd386..53d477a7f88a2dcb40b451db206236aa3e9fd86d 100644
--- a/src/types/models.ts
+++ b/src/types/models.ts
@@ -59,9 +59,11 @@ import { submapConnection } from '@/models/submapConnection';
 import { targetElementSchema } from '@/models/targetElementSchema';
 import { targetSchema } from '@/models/targetSchema';
 import { targetSearchNameResult } from '@/models/targetSearchNameResult';
-import { userPrivilegesSchema } from '@/models/userPrivilegesSchema';
+import { userPrivilegeSchema } from '@/models/userPrivilegesSchema';
 import { z } from 'zod';
 import { commentSchema } from '@/models/commentSchema';
+import { userSchema } from '@/models/userSchema';
+import { javaStacktraceSchema } from '@/models/javaStacktraceSchema';
 
 export type Project = z.infer<typeof projectSchema>;
 export type OverviewImageView = z.infer<typeof overviewImageView>;
@@ -112,11 +114,13 @@ export type GeneVariant = z.infer<typeof geneVariant>;
 export type TargetSearchNameResult = z.infer<typeof targetSearchNameResult>;
 export type TargetElement = z.infer<typeof targetElementSchema>;
 export type SubmapConnection = z.infer<typeof submapConnection>;
-export type UserPrivileges = z.infer<typeof userPrivilegesSchema>;
+export type UserPrivilege = z.infer<typeof userPrivilegeSchema>;
+export type User = z.infer<typeof userSchema>;
 export type MarkerType = z.infer<typeof markerTypeSchema>;
 export type MarkerPin = z.infer<typeof markerPinSchema>;
 export type MarkerSurface = z.infer<typeof markerSurfaceSchema>;
 export type MarkerLine = z.infer<typeof markerLineSchema>;
 export type MarkerWithPosition = z.infer<typeof markerWithPositionSchema>;
 export type Marker = z.infer<typeof markerSchema>;
+export type JavaStacktrace = z.infer<typeof javaStacktraceSchema>;
 export type Comment = z.infer<typeof commentSchema>;
diff --git a/src/utils/error-report/ErrorData.ts b/src/utils/error-report/ErrorData.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3d807d9e0f944503ed56c92e0cdd7459d1c77fa2
--- /dev/null
+++ b/src/utils/error-report/ErrorData.ts
@@ -0,0 +1,12 @@
+export type ErrorData = {
+  url: string | null;
+  login: string | null;
+  email: string | null;
+  browser: string | null;
+  timestamp: number | null;
+  version: string | null;
+  comment: string | null;
+  message: string;
+  stacktrace: string;
+  javaStacktrace: string | null;
+};
diff --git a/src/utils/error-report/errorReporting.test.ts b/src/utils/error-report/errorReporting.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7534585eb016e148acfba0211c8d8501b73eb6de
--- /dev/null
+++ b/src/utils/error-report/errorReporting.test.ts
@@ -0,0 +1,94 @@
+import { createErrorData } from '@/utils/error-report/errorReporting';
+import { apiPath } from '@/redux/apiPath';
+import { HttpStatusCode } from 'axios';
+import { loginFixture } from '@/models/fixtures/loginFixture';
+import { login, logout } from '@/redux/user/user.thunks';
+import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
+import { store } from '@/redux/store';
+import { getConfiguration } from '@/redux/configuration/configuration.thunks';
+import { configurationFixture } from '@/models/fixtures/configurationFixture';
+import { userFixture } from '@/models/fixtures/userFixture';
+import { SerializedError } from '@reduxjs/toolkit';
+import { javaStacktraceFixture } from '@/models/fixtures/javaStacktraceFixture';
+
+const mockedAxiosClient = mockNetworkResponse();
+
+const CREDENTIALS = {
+  login: 'test',
+  password: 'password',
+};
+
+describe('createErrorData', () => {
+  it('should add stacktrace', async () => {
+    const error = await createErrorData(new Error('hello'), store.getState());
+    expect(error.stacktrace).not.toEqual('');
+  });
+
+  it('should add url', async () => {
+    const error = await createErrorData(new Error('hello'), store.getState());
+    expect(error.url).not.toBeNull();
+  });
+
+  it('should add browser', async () => {
+    const error = await createErrorData(new Error('hello'), store.getState());
+    expect(error.browser).not.toBeNull();
+  });
+
+  it('should add guest login when not logged', async () => {
+    const error = await createErrorData(new Error('hello'), store.getState());
+    expect(error.login).toBe('anonymous');
+  });
+
+  it('should add login when logged', async () => {
+    mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
+    await store.dispatch(login(CREDENTIALS));
+
+    const error = await createErrorData(new Error('hello'), store.getState());
+    expect(error.login).not.toBe('anonymous');
+    expect(error.login).toBe(loginFixture.login);
+  });
+
+  it('should add timestamp', async () => {
+    const error = await createErrorData(new Error(), store.getState());
+    expect(error.timestamp).not.toBeNull();
+  });
+
+  it('should add version', async () => {
+    mockedAxiosClient
+      .onGet(apiPath.getConfiguration())
+      .reply(HttpStatusCode.Ok, configurationFixture);
+    await store.dispatch(getConfiguration());
+
+    const error = await createErrorData(new Error(), store.getState());
+    expect(error.version).not.toBeNull();
+  });
+
+  it('should add email when logged', async () => {
+    mockedAxiosClient.onPost(apiPath.postLogin()).reply(HttpStatusCode.Ok, loginFixture);
+    mockedAxiosClient.onGet(apiPath.user(loginFixture.login)).reply(HttpStatusCode.Ok, userFixture);
+    await store.dispatch(login(CREDENTIALS));
+
+    const error = await createErrorData(new Error(), store.getState());
+    expect(error.email).toBe(userFixture.email);
+  });
+
+  it('email should be empty when not logged', async () => {
+    mockedAxiosClient.onPost(apiPath.logout()).reply(HttpStatusCode.Ok, {});
+    await store.dispatch(logout());
+    const error = await createErrorData(new Error(), store.getState());
+    expect(error.email).toBeNull();
+  });
+
+  it('java stacktrace should be attached if error report provides info', async () => {
+    mockedAxiosClient
+      .onGet(apiPath.getStacktrace('dab932be-1e2e-45d7-b57a-aff30e2629e6'))
+      .reply(HttpStatusCode.Ok, javaStacktraceFixture);
+
+    const error: SerializedError = {
+      code: 'dab932be-1e2e-45d7-b57a-aff30e2629e6',
+    };
+    const errorData = await createErrorData(error, store.getState());
+    expect(errorData.javaStacktrace).not.toBeNull();
+  });
+});
diff --git a/src/utils/error-report/errorReporting.ts b/src/utils/error-report/errorReporting.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4bc652535e50df366fad0a6f6cda6afe1f618a02
--- /dev/null
+++ b/src/utils/error-report/errorReporting.ts
@@ -0,0 +1,77 @@
+import { ErrorData } from '@/utils/error-report/ErrorData';
+import { SerializedError } from '@reduxjs/toolkit';
+import { ONE_THOUSAND } from '@/constants/common';
+import {
+  GENERIC_AXIOS_ERROR_CODE,
+  NOT_FOUND_AXIOS_ERROR_CODE,
+  UNKNOWN_AXIOS_ERROR_CODE,
+  UNKNOWN_ERROR,
+} from '@/utils/getErrorMessage/getErrorMessage.constants';
+import { axiosInstance } from '@/services/api/utils/axiosInstance';
+import { JavaStacktrace } from '@/types/models';
+import { apiPath } from '@/redux/apiPath';
+import type { RootState } from '@/redux/store';
+
+export const createErrorData = async (
+  error: Error | SerializedError | undefined,
+  state: RootState,
+): Promise<ErrorData> => {
+  let stacktrace = '';
+  let message = '';
+  if (error !== undefined) {
+    stacktrace = error.stack !== undefined ? error.stack : '';
+    message = error.message !== undefined ? error.message : '';
+  }
+
+  let login = null;
+  let userData = null;
+
+  if (state.user) {
+    login = state.user.login;
+    userData = state.user.userData;
+  }
+  if (!login) {
+    login = 'anonymous';
+  }
+
+  let email = null;
+  if (userData) {
+    email = userData.email;
+  }
+
+  const configuration = state?.configuration?.main?.data;
+  const version = configuration ? configuration.version : null;
+
+  let javaStacktrace = null;
+  if (error !== undefined && 'code' in error) {
+    const { code } = error;
+    if (
+      code &&
+      code !== UNKNOWN_ERROR &&
+      code !== UNKNOWN_AXIOS_ERROR_CODE &&
+      code !== GENERIC_AXIOS_ERROR_CODE &&
+      code !== NOT_FOUND_AXIOS_ERROR_CODE
+    ) {
+      try {
+        javaStacktrace = (await axiosInstance.get<JavaStacktrace>(apiPath.getStacktrace(code))).data
+          .content;
+      } catch (e) {
+        // eslint-disable-next-line no-console
+        console.log('Problem with fetching javaStacktrace', e);
+      }
+    }
+  }
+
+  return {
+    url: window?.location?.href,
+    login,
+    browser: navigator.userAgent,
+    comment: null,
+    email,
+    javaStacktrace,
+    stacktrace,
+    timestamp: Math.floor(+new Date() / ONE_THOUSAND),
+    version,
+    message,
+  };
+};
diff --git a/src/utils/error-report/getError.ts b/src/utils/error-report/getError.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b1da418173ac5d178e1f4fc4e5feee24a4af0ad2
--- /dev/null
+++ b/src/utils/error-report/getError.ts
@@ -0,0 +1,26 @@
+import { getErrorMessage } from '@/utils/getErrorMessage';
+import { SerializedError } from '@reduxjs/toolkit';
+import { getErrorName } from '@/utils/error-report/getErrorName';
+import { getErrorCode } from '@/utils/error-report/getErrorCode';
+import { getErrorStack } from '@/utils/error-report/getErrorStack';
+
+type GetErrorMessageConfig = {
+  error: unknown;
+  message?: string;
+  prefix?: string;
+};
+
+export const getError = ({ error, message, prefix }: GetErrorMessageConfig): SerializedError => {
+  const errorMessage = getErrorMessage({ error, message, prefix });
+
+  const name = getErrorName(error);
+  const stack = getErrorStack(error);
+  const code = getErrorCode(error);
+
+  return {
+    name,
+    message: errorMessage,
+    stack,
+    code,
+  };
+};
diff --git a/src/utils/error-report/getErrorCode.ts b/src/utils/error-report/getErrorCode.ts
new file mode 100644
index 0000000000000000000000000000000000000000..df25ac8e84fcd7fd26e4a27b0b78c2fc4061770e
--- /dev/null
+++ b/src/utils/error-report/getErrorCode.ts
@@ -0,0 +1,27 @@
+import axios from 'axios';
+import {
+  UNKNOWN_AXIOS_ERROR_CODE,
+  UNKNOWN_ERROR,
+} from '../getErrorMessage/getErrorMessage.constants';
+
+export const getErrorCode = (error: unknown): string => {
+  if (axios.isAxiosError(error)) {
+    let code = UNKNOWN_AXIOS_ERROR_CODE;
+    try {
+      if (error.response) {
+        if (typeof error.response.data === 'object') {
+          code = error.response.data['error-id'];
+        } else if (typeof error.response.data === 'string') {
+          code = JSON.parse(error.response.data)['error-id'];
+        }
+        if (code === undefined || code === null) {
+          code = `${error.response.status}`;
+        }
+      }
+    } catch (e) {
+      code = UNKNOWN_AXIOS_ERROR_CODE;
+    }
+    return code;
+  }
+  return UNKNOWN_ERROR;
+};
diff --git a/src/utils/error-report/getErrorName.ts b/src/utils/error-report/getErrorName.ts
new file mode 100644
index 0000000000000000000000000000000000000000..163a0d860c9f3a87809a3262d941b30a692dbca6
--- /dev/null
+++ b/src/utils/error-report/getErrorName.ts
@@ -0,0 +1,12 @@
+import axios from 'axios';
+import { UNKNOWN_ERROR } from '../getErrorMessage/getErrorMessage.constants';
+
+export const getErrorName = (error: unknown): string => {
+  if (axios.isAxiosError(error)) {
+    return error.name;
+  }
+  if (error instanceof Error) {
+    return error.name;
+  }
+  return UNKNOWN_ERROR;
+};
diff --git a/src/utils/error-report/getErrorStack.ts b/src/utils/error-report/getErrorStack.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e148696f16214a786cb7a48ee1862fa3743bbbe2
--- /dev/null
+++ b/src/utils/error-report/getErrorStack.ts
@@ -0,0 +1,14 @@
+import axios from 'axios';
+import { getErrorUrl } from '@/utils/error-report/getErrorUrl';
+
+export const getErrorStack = (error: unknown): string => {
+  let stack = null;
+  if (axios.isAxiosError(error)) {
+    const url = getErrorUrl(error);
+
+    stack = (url ? `(Request URL: ${url}) ` : '') + error.stack;
+  } else if (error instanceof Error) {
+    stack = error.stack;
+  }
+  return stack || 'No stack provided';
+};
diff --git a/src/utils/error-report/getErrorUrl.ts b/src/utils/error-report/getErrorUrl.ts
new file mode 100644
index 0000000000000000000000000000000000000000..53ef46e9f4e5c4bf4bb9541f252594f357c8de8f
--- /dev/null
+++ b/src/utils/error-report/getErrorUrl.ts
@@ -0,0 +1,12 @@
+import axios from 'axios';
+
+export const getErrorUrl = (error: unknown): string | null => {
+  if (axios.isAxiosError(error)) {
+    if (error.request) {
+      if (error.request.responseURL) {
+        return error.request.responseURL;
+      }
+    }
+  }
+  return null;
+};
diff --git a/src/utils/error-report/sendErrorReport.ts b/src/utils/error-report/sendErrorReport.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6fa588214425c86af0d98ffeb2d2e86dcd9e182e
--- /dev/null
+++ b/src/utils/error-report/sendErrorReport.ts
@@ -0,0 +1,20 @@
+import { axiosInstance } from '@/services/api/utils/axiosInstance';
+import { createAsyncThunk } from '@reduxjs/toolkit';
+import { Login } from '@/types/models';
+import { ErrorData } from '@/utils/error-report/ErrorData';
+import { apiPath } from '@/redux/apiPath';
+import { showToast } from '@/utils/showToast';
+
+export const sendReport = createAsyncThunk('error/report', async (errorData: ErrorData) => {
+  try {
+    await axiosInstance.post<Login>(apiPath.submitError(), errorData);
+    showToast({ type: 'success', message: 'Error report sent successfully.' });
+  } catch (error) {
+    // eslint-disable-next-line no-console
+    console.log(error);
+    showToast({
+      type: 'error',
+      message: 'Unexpected error. More information can be found in the console.',
+    });
+  }
+});
diff --git a/src/utils/getErrorMessage/getErrorMessage.constants.ts b/src/utils/getErrorMessage/getErrorMessage.constants.ts
index 00b84d7087cf177ecf1a129633867153ce228e48..e6d05b2732652bf8ceb927f41c324af05b0526b8 100644
--- a/src/utils/getErrorMessage/getErrorMessage.constants.ts
+++ b/src/utils/getErrorMessage/getErrorMessage.constants.ts
@@ -1,4 +1,7 @@
 export const UNKNOWN_ERROR = 'An unknown error occurred. Please try again later.';
+export const UNKNOWN_AXIOS_ERROR_CODE = 'UNKNOWN_AXIOS_ERROR';
+export const NOT_FOUND_AXIOS_ERROR_CODE = '404';
+export const GENERIC_AXIOS_ERROR_CODE = 'ERR_BAD_REQUEST';
 
 export const HTTP_ERROR_MESSAGES = {
   400: "The server couldn't understand your request. Please check your input and try again.",