diff --git a/bigbluebutton-html5/imports/api/audio/client/bridge/kurento.js b/bigbluebutton-html5/imports/api/audio/client/bridge/kurento.js
index 9e32b75222d65233e8b87575bce910703e69a4da..266cd94f69ddc4018d5899876b2855f742eb0941 100755
--- a/bigbluebutton-html5/imports/api/audio/client/bridge/kurento.js
+++ b/bigbluebutton-html5/imports/api/audio/client/bridge/kurento.js
@@ -39,13 +39,14 @@ export default class KurentoAudioBridge extends BaseAudioBridge {
   }
 
   static normalizeError(error = {}) {
-    const errorMessage = error.message || error.name || error.reason || 'Unknown error';
-    const errorCode = error.code || 'Undefined code';
+    const errorMessage = error.name || error.message || error.reason || 'Unknown error';
+    const errorCode = error.code || undefined;
     const errorReason = error.reason || error.id || 'Undefined reason';
 
     return { errorMessage, errorCode, errorReason };
   }
 
+
   joinAudio({ isListenOnly, inputStream }, callback) {
     return new Promise(async (resolve, reject) => {
       this.callback = callback;
diff --git a/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js b/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js
index ee0fc23d555e44694b398c55545befed1892afcb..125c13e7b300ce63f680600db65440eb194ed6b7 100755
--- a/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js
+++ b/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js
@@ -22,34 +22,48 @@ const getSessionToken = () => Auth.sessionToken;
 
 export default class KurentoScreenshareBridge {
   static normalizeError(error = {}) {
-    const errorMessage = error.message || error.name || error.reason || 'Unknown error';
-    const errorCode = error.code || 'Undefined code';
+    const errorMessage = error.name || error.message || error.reason || 'Unknown error';
+    const errorCode = error.code || undefined;
     const errorReason = error.reason || error.id || 'Undefined reason';
 
     return { errorMessage, errorCode, errorReason };
   }
 
-  static handlePresenterFailure(error) {
+  static handlePresenterFailure(error, started = false) {
     const normalizedError = KurentoScreenshareBridge.normalizeError(error);
-    logger.error({
-      logCode: 'screenshare_presenter_error_failed_to_connect',
-      extraInfo: { ...normalizedError },
-    }, `Screenshare presenter failed when trying to start due to ${normalizedError.errorMessage}`);
+    if (!started) {
+      logger.error({
+        logCode: 'screenshare_presenter_error_failed_to_connect',
+        extraInfo: { ...normalizedError },
+      }, `Screenshare presenter failed when trying to start due to ${normalizedError.errorMessage}`);
+    } else {
+      logger.error({
+        logCode: 'screenshare_presenter_error_failed_after_success',
+        extraInfo: { ...normalizedError },
+      }, `Screenshare presenter failed during working session due to ${normalizedError.errorMessage}`);
+    }
     return normalizedError;
   }
 
-  static handleViewerFailure(error) {
+  static handleViewerFailure(error, started = false) {
     const normalizedError = KurentoScreenshareBridge.normalizeError(error);
-    logger.error({
-      logCode: 'screenshare_viewer_error_failed_to_connect',
-      extraInfo: { ...normalizedError },
-    }, `Screenshare viewer failed when trying to start due to ${normalizedError.errorMessage}`);
-
+    if (!started) {
+      logger.error({
+        logCode: 'screenshare_viewer_error_failed_to_connect',
+        extraInfo: { ...normalizedError },
+      }, `Screenshare viewer failed when trying to start due to ${normalizedError.errorMessage}`);
+    } else {
+      logger.error({
+        logCode: 'screenshare_viewer_error_failed_after_success',
+        extraInfo: { ...normalizedError },
+      }, `Screenshare viewer failed during working session due to ${normalizedError.errorMessage}`);
+    }
     return normalizedError;
   }
 
   async kurentoWatchVideo() {
     let iceServers = [];
+    let started = false;
 
     try {
       iceServers = await fetchWebRTCMappedStunTurnServers(getSessionToken());
@@ -110,13 +124,14 @@ export default class KurentoScreenshareBridge {
       };
 
       const onFail = (error) => {
-        KurentoScreenshareBridge.handleViewerFailure(error);
+        KurentoScreenshareBridge.handleViewerFailure(error, started);
       };
 
       // Callback for the kurento-extension.js script. It's called when the whole
       // negotiation with SFU is successful. This will load the stream into the
       // screenshare media element and play it manually.
       const onSuccess = () => {
+        started = true;
         const { webRtcPeer } = window.kurentoManager.kurentoVideo;
         if (webRtcPeer) {
           const stream = webRtcPeer.getRemoteStream();
@@ -160,12 +175,15 @@ export default class KurentoScreenshareBridge {
         logger,
       };
 
+      let started = false;
+
       const failureCallback = (error) => {
-        const normalizedError = KurentoScreenshareBridge.handlePresenterFailure(error);
+        const normalizedError = KurentoScreenshareBridge.handlePresenterFailure(error, started);
         onFail(normalizedError);
       };
 
       const successCallback = () => {
+        started = true;
         logger.info({
           logCode: 'screenshare_presenter_start_success',
         }, 'Screenshare presenter started succesfully');
diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/desktop-share/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/desktop-share/component.jsx
index 5953328500520999dfe4498b73036f485b70f253..ed96a0259a09130c1a30998a5c27180d584b8d81 100755
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/desktop-share/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/desktop-share/component.jsx
@@ -41,10 +41,62 @@ const intlMessages = defineMessages({
     id: 'app.actionsBar.actionsDropdown.stopDesktopShareDesc',
     description: 'adds context to stop desktop share option',
   },
-  iceConnectionStateError: {
+  genericError: {
+    id: 'app.screenshare.genericError',
+    description: 'error message for when screensharing fails with unknown error',
+  },
+  NotAllowedError: {
+    id: 'app.screenshare.notAllowed',
+    description: 'error message when screen access was not granted',
+  },
+  NotSupportedError: {
+    id: 'app.screenshare.notSupportedError',
+    description: 'error message when trying to share screen in unsafe environments',
+  },
+  NotReadableError: {
+    id: 'app.screenshare.notReadableError',
+    description: 'error message when the browser failed to capture the screen',
+  },
+  1108: {
     id: 'app.deskshare.iceConnectionStateError',
     description: 'Error message for ice connection state failure',
   },
+  2000: {
+    id: 'app.sfu.mediaServerConnectionError2000',
+    description: 'Error message fired when the SFU cannot connect to the media server',
+  },
+  2001: {
+    id: 'app.sfu.mediaServerOffline2001',
+    description: 'error message when SFU is offline',
+  },
+  2002: {
+    id: 'app.sfu.mediaServerNoResources2002',
+    description: 'Error message fired when the media server lacks disk, CPU or FDs',
+  },
+  2003: {
+    id: 'app.sfu.mediaServerRequestTimeout2003',
+    description: 'Error message fired when requests are timing out due to lack of resources',
+  },
+  2021: {
+    id: 'app.sfu.serverIceGatheringFailed2021',
+    description: 'Error message fired when the server cannot enact ICE gathering',
+  },
+  2022: {
+    id: 'app.sfu.serverIceStateFailed2022',
+    description: 'Error message fired when the server endpoint transitioned to a FAILED ICE state',
+  },
+  2200: {
+    id: 'app.sfu.mediaGenericError2200',
+    description: 'Error message fired when the SFU component generated a generic error',
+  },
+  2202: {
+    id: 'app.sfu.invalidSdp2202',
+    description: 'Error message fired when the clients provides an invalid SDP',
+  },
+  2203: {
+    id: 'app.sfu.noAvailableCodec2203',
+    description: 'Error message fired when the server has no available codec for the client',
+  },
 });
 
 const BROWSER_RESULTS = browser();
@@ -53,8 +105,6 @@ const isMobileBrowser = (BROWSER_RESULTS ? BROWSER_RESULTS.mobile : false)
     ? BROWSER_RESULTS.os.includes('Android') // mobile flag doesn't always work
     : false);
 
-const ICE_CONNECTION_FAILED = 'ICE connection failed';
-
 const DesktopShare = ({
   intl,
   handleShareScreen,
@@ -66,23 +116,29 @@ const DesktopShare = ({
   isMeteorConnected,
   screenshareDataSavingSetting,
 }) => {
-  const onFail = (error) => {
-    switch (error) {
-      case ICE_CONNECTION_FAILED:
-        kurentoExitScreenShare();
-        logger.error({ logCode: 'desktopshare_iceconnectionstate_error' }, 'ICE connection state error');
-        notify(intl.formatMessage(intlMessages.iceConnectionStateError), 'error', 'desktop');
-        break;
-      default:
-        logger.error({
-          logCode: 'desktopshare_default_error',
-          extraInfo: {
-            maybeError: error || 'Default error handler',
-          },
-        }, 'Default error handler for screenshare');
+  // This is the failure callback that will be passed to the /api/screenshare/kurento.js
+  // script on the presenter's call
+  const onFail = (normalizedError) => {
+    const { errorCode, errorMessage, errorReason } = normalizedError;
+    const error = errorCode || errorMessage || errorReason;
+    // We have a properly mapped error for this. Exit screenshare and show  a toast notification
+    if (intlMessages[error]) {
+      window.kurentoExitScreenShare();
+      notify(intl.formatMessage(intlMessages[error]), 'error', 'desktop');
+    } else {
+      // Unmapped error. Log it (so we can infer what's going on), close screenSharing
+      // session and display generic error message
+      logger.error({
+        logCode: 'screenshare_default_error',
+        extraInfo: {
+          errorCode, errorMessage, errorReason,
+        },
+      }, 'Default error handler for screenshare');
+      window.kurentoExitScreenShare();
+      notify(intl.formatMessage(intlMessages.genericError), 'error', 'desktop');
     }
     // Don't trigger the screen share end alert if presenter click to cancel on screen share dialog
-    if (error && error.name !== 'NotAllowedError') {
+    if (error !== 'NotAllowedError') {
       screenShareEndAlert();
     }
   };
@@ -100,7 +156,7 @@ const DesktopShare = ({
     ? (
       <Button
         className={cx(styles.button, isVideoBroadcasting || styles.btn)}
-        disabled={!isMeteorConnected && !isVideoBroadcasting || !screenshareDataSavingSetting}
+        disabled={(!isMeteorConnected && !isVideoBroadcasting) || !screenshareDataSavingSetting}
         icon={isVideoBroadcasting ? 'desktop' : 'desktop_off'}
         label={intl.formatMessage(vLabel)}
         description={intl.formatMessage(vDescr)}
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index 82b37c50c318e4302bc1bb3b59f7b4cc55a4f75b..3cfeb03dac6eeaece7227d81a8960dce98d73098 100755
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -115,6 +115,10 @@
     "app.media.screenshare.safariNotSupported": "Screenshare is currently not supported by Safari. Please, use Firefox or Google Chrome.",
     "app.media.screenshare.autoplayBlockedDesc": "We need your permission to show you the presenter's screen.",
     "app.media.screenshare.autoplayAllowLabel": "View shared screen",
+    "app.screenshare.notAllowed": "Error: Permission to access screen wasn't granted.",
+    "app.screenshare.notSupportedError": "Error: Screensharing is allowed only on safe (SSL) domains",
+    "app.screenshare.notReadableError": "Error: There was a failure while trying to capture your screen",
+    "app.screenshare.genericError": "Error: An error has occurred with screensharing, please try again",
     "app.meeting.ended": "This session has ended",
     "app.meeting.meetingTimeRemaining": "Meeting time remaining: {0}",
     "app.meeting.meetingTimeHasEnded": "Time ended. Meeting will close soon",
diff --git a/bigbluebutton-html5/public/compatibility/kurento-extension.js b/bigbluebutton-html5/public/compatibility/kurento-extension.js
index 2c9298c441058b58aa62b849f5cc3d91add04261..e74f643598a7b0c035b973c997e897ab0d36a283 100755
--- a/bigbluebutton-html5/public/compatibility/kurento-extension.js
+++ b/bigbluebutton-html5/public/compatibility/kurento-extension.js
@@ -492,7 +492,7 @@ Kurento.prototype.startScreensharing = function () {
           logCode: 'kurentoextension_screenshare_presenter_ice_failed',
           extraInfo: { iceConnectionState }
         }, `WebRTC peer for screenshare presenter failed due to ICE transitioning to ${iceConnectionState}`);
-        this.onFail('ICE connection failed');
+        this.onFail({ message: 'iceConnectionStateError', code: 1108 });
       }
     }
   };
@@ -555,7 +555,7 @@ Kurento.prototype.viewer = function () {
             logCode: 'kurentoextension_screenshare_viewer_ice_failed',
             extraInfo: { iceConnectionState }
           }, `WebRTC peer for screenshare viewer failed due to ICE transitioning to ${iceConnectionState}`);
-          this.onFail('ICE connection failed');
+          this.onFail({ message: 'iceConnectionStateError', code: 1108 });
         }
       }
     };