diff --git a/docs/plugins/errors.md b/docs/plugins/errors.md
index ddbebcf587a4a937fce41741757f708d27b9e385..25f1210aeafb1852777856d94544782ab1bb3246 100644
--- a/docs/plugins/errors.md
+++ b/docs/plugins/errors.md
@@ -39,3 +39,11 @@
 - **Provided zoom value exeeds max zoom of ...**: This error occurs when `zoom` param of `setZoom` exeeds max zoom value of the selected map
 
 - **Provided zoom value exceeds min zoom of ...**: This error occurs when `zoom` param of `setZoom` exceeds min zoom value of the selected map
+
+## Event Errors
+
+- **Invalid event type: ...**: This error occurs when an event type is not allowed or recognized.
+
+## Plugin Errors
+
+- **Plugin "..." has crashed. Please contact the plugin developer for assistance**: This error occurs when a plugin encounters an unexpected error and crashes. Users are advised to contact the plugin developer for assistance.
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.ts b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.ts
index a14476cfb9650068b07a5185a0337441675bf09f..6ebfcea929a1c0472f8cf3493ab39056b475b823 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.ts
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPlugin/hooks/useLoadPlugin.ts
@@ -46,16 +46,18 @@ export const useLoadPlugin = ({
   const handleLoadPlugin = async (): Promise<void> => {
     try {
       const response = await axios(pluginUrl);
-      const pluginScript = response.data;
-
-      /* eslint-disable no-new-func */
-      const loadPlugin = new Function(pluginScript);
+      let pluginScript = response.data;
 
       PluginsManager.setHashedPlugin({
         pluginUrl,
         pluginScript,
       });
 
+      pluginScript += `//# sourceURL=${pluginUrl}`;
+
+      /* eslint-disable no-new-func */
+      const loadPlugin = new Function(pluginScript);
+
       loadPlugin();
 
       if (onPluginLoaded) {
diff --git a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
index f95bdf7e4beaa78a655090c648652a8ff20fa388..1b7c935f9365a150d9c0abfff44f20643d4c0d0f 100644
--- a/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
+++ b/src/components/Map/Drawer/AvailablePluginsDrawer/LoadPluginFromUrl/hooks/useLoadPluginFromUrl.ts
@@ -35,16 +35,18 @@ export const useLoadPluginFromUrl = (): UseLoadPluginReturnType => {
     try {
       setIsLoading(true);
       const response = await axios(pluginUrl);
-      const pluginScript = response.data;
-
-      /* eslint-disable no-new-func */
-      const loadPlugin = new Function(pluginScript);
+      let pluginScript = response.data;
 
       const hash = PluginsManager.setHashedPlugin({
         pluginUrl,
         pluginScript,
       });
 
+      pluginScript += `//# sourceURL=${pluginUrl}`;
+
+      /* eslint-disable no-new-func */
+      const loadPlugin = new Function(pluginScript);
+
       if (!(hash in activePlugins)) {
         loadPlugin();
       }
diff --git a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts
index 4daa661f7202dc3f6137bb1d579267e0b45aefd2..289742415aeeb8d5fb4f5867871a449558c8f3bd 100644
--- a/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts
+++ b/src/components/Map/MapViewer/utils/listeners/mapSingleClick/handleReactionResults.test.ts
@@ -61,40 +61,40 @@ describe('handleReactionResults - util', () => {
     expect(actions[1].type).toEqual('reactions/getByIds/fulfilled');
   });
 
-  it('should run openReactionDrawerById to empty array as second action', () => {
+  it('should run openReactionDrawerById to empty array as third action', () => {
     const actions = store.getActions();
     expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
     expect(actions[2].type).toEqual('drawer/openReactionDrawerById');
     expect(actions[2].payload).toEqual(reactionsFixture[FIRST_ARRAY_ELEMENT].id);
   });
 
-  it('should run select tab as third action', () => {
+  it('should run select tab as fourth action', () => {
     const actions = store.getActions();
     expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
     expect(actions[3].type).toEqual('drawer/selectTab');
   });
 
-  it('should run setBioEntityContent to empty array as third action', () => {
+  it('should run getMultiBioEntity to empty array as fifth action', () => {
     const actions = store.getActions();
     expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
     expect(actions[4].type).toEqual('project/getMultiBioEntity/pending');
   });
 
-  it('should run getBioEntityContents as fourth action', () => {
+  it('should run getBioEntityContents as sixth action', () => {
     const actions = store.getActions();
     expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
     expect(actions[5].type).toEqual('project/getBioEntityContents/pending');
   });
 
-  it('should run getBioEntityContents fullfilled as fourth action', () => {
+  it('should run getBioEntityContents fullfilled as seventh action', () => {
     const actions = store.getActions();
     expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
-    expect(actions[5].type).toEqual('project/getBioEntityContents/fulfilled');
+    expect(actions[6].type).toEqual('project/getBioEntityContents/fulfilled');
   });
 
-  it('should run addNumbersToEntityNumberData as fifth action', () => {
+  it('should run addNumbersToEntityNumberData as eighth action', () => {
     const actions = store.getActions();
     expect(actions.length).toBeGreaterThan(SIZE_OF_EMPTY_ARRAY);
-    expect(actions[6].type).toEqual('entityNumber/addNumbersToEntityNumberData');
+    expect(actions[7].type).toEqual('entityNumber/addNumbersToEntityNumberData');
   });
 });
diff --git a/src/redux/plugins/plugins.thunks.ts b/src/redux/plugins/plugins.thunks.ts
index 1d69a6cbb318e9a02a78ce882e9c638199ebd324..76dc4491488086e5a89990ecd8d4fda2593cedff 100644
--- a/src/redux/plugins/plugins.thunks.ts
+++ b/src/redux/plugins/plugins.thunks.ts
@@ -85,11 +85,14 @@ export const getInitPlugins = createAsyncThunk<void, GetInitPluginsProps, ThunkC
         if (isDataValid) {
           const { urls } = res.data;
           const scriptRes = await axios(urls[0]);
-          const pluginScript = scriptRes.data;
+          let pluginScript = scriptRes.data;
           setHashedPlugin({ pluginUrl: urls[0], pluginScript });
 
+          pluginScript += `//# sourceURL=${urls[0]}`;
+
           /* eslint-disable no-new-func */
           const loadPlugin = new Function(pluginScript);
+
           loadPlugin();
         }
       }
diff --git a/src/services/pluginsManager/errorMessages.ts b/src/services/pluginsManager/errorMessages.ts
index a5d4615034fb7656a01bb008ed2f3013a88f8a67..029b14e0e9f0f6256aca438d65b7e1914b219ff0 100644
--- a/src/services/pluginsManager/errorMessages.ts
+++ b/src/services/pluginsManager/errorMessages.ts
@@ -12,3 +12,6 @@ export const ERROR_OVERLAY_ID_NOT_ACTIVE = 'Overlay with provided id is not acti
 export const ERROR_OVERLAY_ID_ALREADY_ACTIVE = 'Overlay with provided id is already active';
 export const ERROR_INVALID_MODEL_ID_TYPE_FOR_RETRIEVAL =
   'Unable to retrieve the id of the active map: the modelId is not a number';
+export const ERROR_INVALID_EVENT_TYPE = (type: string): string => `Invalid event type: ${type}`;
+export const ERROR_PLUGIN_CRASH = (pluginName: string): string =>
+  `Plugin "${pluginName}" has crashed. Please contact the plugin developer for assistance`;
diff --git a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.test.ts b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.test.ts
index 474b9d214ce9d920b94c2a473cf052201294b496..c90919b45b79d6052fe4e215286838f25f4f0c85 100644
--- a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.test.ts
+++ b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.test.ts
@@ -1,6 +1,22 @@
 /* eslint-disable no-magic-numbers */
 import { createdOverlayFixture } from '@/models/fixtures/overlaysFixture';
+import { RootState, store } from '@/redux/store';
+
+import { PLUGINS_MOCK } from '@/models/mocks/pluginsMock';
+import { FIRST_ARRAY_ELEMENT, SECOND_ARRAY_ELEMENT, THIRD_ARRAY_ELEMENT } from '@/constants/common';
+import {
+  PLUGINS_INITIAL_STATE_LIST_MOCK,
+  PLUGINS_INITIAL_STATE_MOCK,
+} from '@/redux/plugins/plugins.mock';
+import { showToast } from '@/utils/showToast';
 import { PluginsEventBus } from './pluginsEventBus';
+import { ERROR_INVALID_EVENT_TYPE, ERROR_PLUGIN_CRASH } from '../errorMessages';
+
+const plugin = PLUGINS_MOCK[FIRST_ARRAY_ELEMENT];
+const secondPlugin = PLUGINS_MOCK[SECOND_ARRAY_ELEMENT];
+const thirdPlugin = PLUGINS_MOCK[THIRD_ARRAY_ELEMENT];
+
+jest.mock('../../../utils/showToast');
 
 describe('PluginsEventBus', () => {
   beforeEach(() => {
@@ -8,12 +24,13 @@ describe('PluginsEventBus', () => {
   });
   it('should store event listener', () => {
     const callback = jest.fn();
-    PluginsEventBus.addListener('123', 'onAddDataOverlay', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onAddDataOverlay', callback);
 
     expect(PluginsEventBus.events).toEqual([
       {
-        hash: '123',
+        hash: plugin.hash,
         type: 'onAddDataOverlay',
+        pluginName: plugin.name,
         callback,
       },
     ]);
@@ -21,7 +38,7 @@ describe('PluginsEventBus', () => {
 
   it('should dispatch event correctly', () => {
     const callback = jest.fn();
-    PluginsEventBus.addListener('123', 'onAddDataOverlay', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onAddDataOverlay', callback);
     PluginsEventBus.dispatchEvent('onAddDataOverlay', createdOverlayFixture);
 
     expect(callback).toHaveBeenCalled();
@@ -30,29 +47,31 @@ describe('PluginsEventBus', () => {
   it('should throw error if event type is incorrect', () => {
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     expect(() => PluginsEventBus.dispatchEvent('onData' as any, createdOverlayFixture)).toThrow(
-      'Invalid event type: onData',
+      ERROR_INVALID_EVENT_TYPE('onData'),
     );
   });
   it('should remove listener only for specific plugin, event type, and callback', () => {
     const callback = (): void => {};
 
-    PluginsEventBus.addListener('123', 'onAddDataOverlay', callback);
-    PluginsEventBus.addListener('123', 'onBioEntityClick', callback);
-    PluginsEventBus.addListener('234', 'onBioEntityClick', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onAddDataOverlay', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onBioEntityClick', callback);
+    PluginsEventBus.addListener(secondPlugin.hash, secondPlugin.name, 'onBioEntityClick', callback);
 
     expect(PluginsEventBus.events).toHaveLength(3);
 
-    PluginsEventBus.removeListener('123', 'onAddDataOverlay', callback);
+    PluginsEventBus.removeListener(plugin.hash, 'onAddDataOverlay', callback);
     expect(PluginsEventBus.events).toHaveLength(2);
     expect(PluginsEventBus.events).toEqual([
       {
         callback,
-        hash: '123',
+        hash: plugin.hash,
+        pluginName: plugin.name,
         type: 'onBioEntityClick',
       },
       {
         callback,
-        hash: '234',
+        hash: secondPlugin.hash,
+        pluginName: secondPlugin.name,
         type: 'onBioEntityClick',
       },
     ]);
@@ -60,13 +79,13 @@ describe('PluginsEventBus', () => {
   it('should throw if listener is not defined by plugin', () => {
     const callback = (): void => {};
 
-    PluginsEventBus.addListener('123', 'onAddDataOverlay', callback);
-    PluginsEventBus.addListener('123', 'onBioEntityClick', callback);
-    PluginsEventBus.addListener('234', 'onBioEntityClick', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onAddDataOverlay', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onBioEntityClick', callback);
+    PluginsEventBus.addListener(secondPlugin.hash, secondPlugin.name, 'onBioEntityClick', callback);
 
     expect(PluginsEventBus.events).toHaveLength(3);
 
-    expect(() => PluginsEventBus.removeListener('123', 'onHideOverlay', callback)).toThrow(
+    expect(() => PluginsEventBus.removeListener(plugin.hash, 'onHideOverlay', callback)).toThrow(
       "Listener doesn't exist",
     );
     expect(PluginsEventBus.events).toHaveLength(3);
@@ -75,43 +94,117 @@ describe('PluginsEventBus', () => {
     const callback = (): void => {};
     const secondCallback = (): void => {};
 
-    PluginsEventBus.addListener('123', 'onAddDataOverlay', callback);
-    PluginsEventBus.addListener('123', 'onAddDataOverlay', secondCallback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onAddDataOverlay', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onAddDataOverlay', secondCallback);
 
-    PluginsEventBus.removeListener('123', 'onAddDataOverlay', callback);
+    PluginsEventBus.removeListener(plugin.hash, 'onAddDataOverlay', callback);
 
     expect(PluginsEventBus.events).toHaveLength(1);
     expect(PluginsEventBus.events).toEqual([
       {
         callback: secondCallback,
-        hash: '123',
+        hash: plugin.hash,
+        pluginName: plugin.name,
         type: 'onAddDataOverlay',
       },
     ]);
   });
   it('should remove all listeners defined by specific plugin', () => {
     const callback = (): void => {};
-    PluginsEventBus.addListener('123', 'onAddDataOverlay', callback);
-    PluginsEventBus.addListener('123', 'onBackgroundOverlayChange', callback);
-    PluginsEventBus.addListener('251', 'onSubmapOpen', callback);
-    PluginsEventBus.addListener('123', 'onHideOverlay', callback);
-    PluginsEventBus.addListener('123', 'onSubmapOpen', callback);
-    PluginsEventBus.addListener('992', 'onSearch', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onAddDataOverlay', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onBackgroundOverlayChange', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onSubmapOpen', callback);
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onHideOverlay', callback);
+    PluginsEventBus.addListener(secondPlugin.hash, secondPlugin.name, 'onSubmapOpen', callback);
+    PluginsEventBus.addListener(thirdPlugin.hash, thirdPlugin.name, 'onSearch', callback);
 
-    PluginsEventBus.removeAllListeners('123');
+    PluginsEventBus.removeAllListeners(plugin.hash);
 
     expect(PluginsEventBus.events).toHaveLength(2);
     expect(PluginsEventBus.events).toEqual([
       {
         callback,
-        hash: '251',
+        hash: secondPlugin.hash,
         type: 'onSubmapOpen',
+        pluginName: secondPlugin.name,
       },
       {
         callback,
-        hash: '992',
+        hash: thirdPlugin.hash,
         type: 'onSearch',
+        pluginName: thirdPlugin.name,
       },
     ]);
   });
+  it('should show toast when event callback provided by plugin throws error', () => {
+    const getStateSpy = jest.spyOn(store, 'getState');
+    getStateSpy.mockImplementation(
+      () =>
+        ({
+          plugins: {
+            ...PLUGINS_INITIAL_STATE_MOCK,
+            activePlugins: {
+              data: {
+                [plugin.hash]: plugin,
+              },
+              pluginsId: [plugin.hash],
+            },
+            list: PLUGINS_INITIAL_STATE_LIST_MOCK,
+          },
+        }) as RootState,
+    );
+
+    const callbackMock = jest.fn(() => {
+      throw new Error('Invalid callback');
+    });
+
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onPluginUnload', callbackMock);
+
+    PluginsEventBus.dispatchEvent('onPluginUnload', {
+      hash: plugin.hash,
+    });
+
+    expect(callbackMock).toHaveBeenCalled();
+    expect(callbackMock).toThrow('Invalid callback');
+    expect(showToast).toHaveBeenCalledWith({
+      message: ERROR_PLUGIN_CRASH(plugin.name),
+      type: 'error',
+    });
+  });
+  it('should call all event callbacks for specific event type even if one event callback provided by plugin throws error', () => {
+    const getStateSpy = jest.spyOn(store, 'getState');
+    getStateSpy.mockImplementation(
+      () =>
+        ({
+          plugins: {
+            ...PLUGINS_INITIAL_STATE_MOCK,
+            activePlugins: {
+              data: {
+                [plugin.hash]: plugin,
+              },
+              pluginsId: [plugin.hash],
+            },
+            list: PLUGINS_INITIAL_STATE_LIST_MOCK,
+          },
+        }) as RootState,
+    );
+
+    const errorCallbackMock = jest.fn(() => {
+      throw new Error('Invalid callback');
+    });
+
+    const callbackMock = jest.fn(() => {
+      return 'plguin';
+    });
+
+    PluginsEventBus.addListener(plugin.hash, plugin.name, 'onSubmapOpen', errorCallbackMock);
+    PluginsEventBus.addListener(secondPlugin.hash, secondPlugin.name, 'onSubmapOpen', callbackMock);
+
+    PluginsEventBus.dispatchEvent('onSubmapOpen', 109);
+
+    expect(errorCallbackMock).toHaveBeenCalled();
+    expect(errorCallbackMock).toThrow('Invalid callback');
+
+    expect(callbackMock).toHaveBeenCalled();
+  });
 });
diff --git a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.ts b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.ts
index 7ca8a74b6529806d7c81de339b756892698c2283..9ff0bbce2e297e2012be88766bb3f07099dcd6c3 100644
--- a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.ts
+++ b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.ts
@@ -1,6 +1,6 @@
 /* eslint-disable no-magic-numbers */
 import { CreatedOverlay, MapOverlay } from '@/types/models';
-import { ALLOWED_PLUGINS_EVENTS, LISTENER_NOT_FOUND } from './pluginsEventBus.constants';
+import { showToast } from '@/utils/showToast';
 import type {
   CenteredCoordinates,
   ClickedBioEntity,
@@ -13,6 +13,8 @@ import type {
   SearchData,
   ZoomChanged,
 } from './pluginsEventBus.types';
+import { ALLOWED_PLUGINS_EVENTS, LISTENER_NOT_FOUND } from './pluginsEventBus.constants';
+import { ERROR_INVALID_EVENT_TYPE, ERROR_PLUGIN_CRASH } from '../errorMessages';
 
 export function dispatchEvent(type: 'onPluginUnload', data: PluginUnloaded): void;
 export function dispatchEvent(type: 'onAddDataOverlay', createdOverlay: CreatedOverlay): void;
@@ -29,12 +31,21 @@ export function dispatchEvent(type: 'onPinIconClick', data: ClickedPinIcon): voi
 export function dispatchEvent(type: 'onSurfaceClick', data: ClickedSurfaceOverlay): void;
 export function dispatchEvent(type: 'onSearch', data: SearchData): void;
 export function dispatchEvent(type: Events, data: EventsData): void {
-  if (!ALLOWED_PLUGINS_EVENTS.includes(type)) throw new Error(`Invalid event type: ${type}`);
+  if (!ALLOWED_PLUGINS_EVENTS.includes(type)) throw new Error(ERROR_INVALID_EVENT_TYPE(type));
 
   // eslint-disable-next-line no-restricted-syntax, no-use-before-define
   for (const event of PluginsEventBus.events) {
     if (event.type === type) {
-      event.callback(data);
+      try {
+        event.callback(data);
+      } catch (error) {
+        showToast({
+          message: ERROR_PLUGIN_CRASH(event.pluginName),
+          type: 'error',
+        });
+        // eslint-disable-next-line no-console
+        console.error(error);
+      }
     }
   }
 }
@@ -42,9 +53,15 @@ export function dispatchEvent(type: Events, data: EventsData): void {
 export const PluginsEventBus: PluginsEventBusType = {
   events: [],
 
-  addListener: (hash: string, type: Events, callback: (data: unknown) => void) => {
+  addListener: (
+    hash: string,
+    pluginName: string,
+    type: Events,
+    callback: (data: unknown) => void,
+  ) => {
     PluginsEventBus.events.push({
       hash,
+      pluginName,
       type,
       callback,
     });
diff --git a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts
index 9e5a86aaf26dfb6169edb7cffcb2e31d3c7bf692..fa6d70e4801de397b941fdf088b811ae62c02fb6 100644
--- a/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts
+++ b/src/services/pluginsManager/pluginsEventBus/pluginsEventBus.types.ts
@@ -92,10 +92,16 @@ export type EventsData =
 export type PluginsEventBusType = {
   events: {
     hash: string;
+    pluginName: string;
     type: Events;
     callback: (data: unknown) => void;
   }[];
-  addListener: (hash: string, type: Events, callback: (data: unknown) => void) => void;
+  addListener: (
+    hash: string,
+    pluginName: string,
+    type: Events,
+    callback: (data: unknown) => void,
+  ) => void;
   removeListener: (hash: string, type: Events, callback: unknown) => void;
   removeAllListeners: (hash: string) => void;
   dispatchEvent: typeof dispatchEvent;
diff --git a/src/services/pluginsManager/pluginsManager.ts b/src/services/pluginsManager/pluginsManager.ts
index e8e4b92407c4d85c68830f36f8e77e9491edbbff..bb42708664d32c5d9119619c242337d20839c7d6 100644
--- a/src/services/pluginsManager/pluginsManager.ts
+++ b/src/services/pluginsManager/pluginsManager.ts
@@ -130,7 +130,7 @@ export const PluginsManager: PluginsManagerType = {
     return {
       element,
       events: {
-        addListener: PluginsEventBus.addListener.bind(this, hash),
+        addListener: PluginsEventBus.addListener.bind(this, hash, pluginName),
         removeListener: PluginsEventBus.removeListener.bind(this, hash),
         removeAllListeners: PluginsEventBus.removeAllListeners.bind(this, hash),
       },