diff --git a/bigbluebutton-html5/client/compatibility/kurento-extension.js b/bigbluebutton-html5/client/compatibility/kurento-extension.js
index cdfc720654b3def6fc16fce9e557cc07b3ed7e32..4ca52d78a9b90bdf298d19a5b835d763f922e72e 100644
--- a/bigbluebutton-html5/client/compatibility/kurento-extension.js
+++ b/bigbluebutton-html5/client/compatibility/kurento-extension.js
@@ -13,7 +13,6 @@ Kurento = function (
   onSuccess,
   options = {},
 ) {
-
   this.ws = null;
   this.video = null;
   this.screen = null;
@@ -30,10 +29,10 @@ Kurento = function (
 
   Object.assign(this, options);
 
-  this.SEND_ROLE = "send";
-  this.RECV_ROLE = "recv";
-  this.SFU_APP = "screenshare";
-  this.ON_ICE_CANDIDATE_MSG = "iceCandidate";
+  this.SEND_ROLE = 'send';
+  this.RECV_ROLE = 'recv';
+  this.SFU_APP = 'screenshare';
+  this.ON_ICE_CANDIDATE_MSG = 'iceCandidate';
   this.PING_INTERVAL = 15000;
 
   window.Logger = this.logger || console;
@@ -45,11 +44,11 @@ Kurento = function (
   }
 
   if (this.chromeScreenshareSources == null) {
-    this.chromeScreenshareSources = ["screen", "window"];
+    this.chromeScreenshareSources = ['screen', 'window'];
   }
 
   if (this.firefoxScreenshareSource == null) {
-    this.firefoxScreenshareSource = "window";
+    this.firefoxScreenshareSource = 'window';
   }
 
   // Limiting max resolution to WQXGA
@@ -78,7 +77,7 @@ Kurento = function (
   if (onSuccess != null) {
     this.onSuccess = Kurento.normalizeCallback(onSuccess);
   } else {
-    var _this = this;
+    const _this = this;
     this.onSuccess = function () {
       _this.logSuccess('Default success handler');
     };
@@ -93,7 +92,6 @@ this.KurentoManager = function () {
 
 KurentoManager.prototype.exitScreenShare = function () {
   if (typeof this.kurentoScreenshare !== 'undefined' && this.kurentoScreenshare) {
-
     if (this.kurentoScreenshare.logger !== null) {
       this.kurentoScreenshare.logger.info('  [exitScreenShare] Exiting screensharing');
     }
@@ -119,6 +117,10 @@ KurentoManager.prototype.exitScreenShare = function () {
 KurentoManager.prototype.exitVideo = function () {
   if (typeof this.kurentoVideo !== 'undefined' && this.kurentoVideo) {
 
+    if(this.kurentoVideo.webRtcPeer) {
+      this.kurentoVideo.webRtcPeer.peerConnection.oniceconnectionstatechange = null;
+    }
+
     if (this.kurentoVideo.logger !== null) {
       this.kurentoVideo.logger.info('  [exitScreenShare] Exiting screensharing viewing');
     }
@@ -139,7 +141,6 @@ KurentoManager.prototype.exitVideo = function () {
 
 KurentoManager.prototype.exitAudio = function () {
   if (typeof this.kurentoAudio !== 'undefined' && this.kurentoAudio) {
-
     if (this.kurentoAudio.logger !== null) {
       this.kurentoAudio.logger.info('  [exitAudio] Exiting listen only audio');
     }
@@ -177,15 +178,15 @@ KurentoManager.prototype.joinWatchVideo = function (tag) {
 
 KurentoManager.prototype.getFirefoxScreenshareSource = function () {
   return this.kurentoScreenshare.firefoxScreenshareSource;
-}
+};
 
 KurentoManager.prototype.getChromeScreenshareSources = function () {
   return this.kurentoScreenshare.chromeScreenshareSources;
-}
+};
 
 KurentoManager.prototype.getChromeExtensionKey = function () {
   return this.kurentoScreenshare.chromeExtension;
-}
+};
 
 
 Kurento.prototype.setScreensharing = function (tag) {
@@ -201,13 +202,13 @@ Kurento.prototype.create = function (tag) {
 Kurento.prototype.downscaleResolution = function (oldWidth, oldHeight) {
   const factorWidth = this.vid_max_width / oldWidth;
   const factorHeight = this.vid_max_height / oldHeight;
-  let width, height;
+  let width,
+    height;
 
   if (factorWidth < factorHeight) {
     width = Math.trunc(oldWidth * factorWidth);
     height = Math.trunc(oldHeight * factorWidth);
-  }
-  else {
+  } else {
     width = Math.trunc(oldWidth * factorHeight);
     height = Math.trunc(oldHeight * factorHeight);
   }
@@ -269,13 +270,12 @@ Kurento.prototype.setRenderTag = function (tag) {
 Kurento.prototype.startResponse = function (message) {
   if (message.response !== 'accepted') {
     const errorMsg = message.message ? message.message : 'Unknow error';
-    this.logger.warn("Call not accepted for the following reason:", {error: errorMsg});
+    this.logger.warn('Call not accepted for the following reason:', { error: errorMsg });
     switch (message.type) {
       case 'screenshare':
         if (message.role === this.SEND_ROLE) {
           kurentoManager.exitScreenShare();
-        }
-        else if (message.role === this.RECV_ROLE) {
+        } else if (message.role === this.RECV_ROLE) {
           kurentoManager.exitVideo();
         }
         break;
@@ -284,7 +284,7 @@ Kurento.prototype.startResponse = function (message) {
         break;
     }
   } else {
-    this.logger.debug(`Procedure for ${message.type} was accepted with SDP =>`, {sdpAnswer: message.sdpAnswer});
+    this.logger.debug(`Procedure for ${message.type} was accepted with SDP =>`, { sdpAnswer: message.sdpAnswer });
     this.webRtcPeer.processAnswer(message.sdpAnswer);
   }
 };
@@ -310,7 +310,7 @@ Kurento.prototype.onOfferPresenter = function (error, offerSdp) {
     vw: this.width,
   };
 
-  this.logger.info("onOfferPresenter sending to screenshare server => ", { sdpOffer: message });
+  this.logger.info('onOfferPresenter sending to screenshare server => ', { sdpOffer: message });
   this.sendMessage(message);
 };
 
@@ -335,7 +335,7 @@ Kurento.prototype.startScreensharing = function () {
     sendSource: 'desktop',
   };
 
-  this.logger.info(" Peer options =>", options);
+  this.logger.info(' Peer options =>', options);
 
   let resolution;
   this.logger.debug(`Screenshare screen dimensions are ${this.width} x ${this.height}`);
@@ -343,23 +343,25 @@ Kurento.prototype.startScreensharing = function () {
     resolution = this.downscaleResolution(this.width, this.height);
     this.width = resolution.width;
     this.height = resolution.height;
-    this.logger.debug("Screenshare track dimensions have been resized to", this.width, "x", this.height);
+    this.logger.debug('Screenshare track dimensions have been resized to', this.width, 'x', this.height);
   }
 
   this.addIceServers(this.iceServers, options);
 
   this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, (error) => {
     if (error) {
-      this.logger.error("WebRtcPeerSendonly constructor error:", {error});
+      this.logger.error('WebRtcPeerSendonly constructor error:', { error });
       this.onFail(error);
       return kurentoManager.exitScreenShare();
     }
 
     this.webRtcPeer.generateOffer(this.onOfferPresenter.bind(this));
-    this.logger.info("Generated peer offer w/ options:", {options: options});
+    this.logger.info('Generated peer offer w/ options:', { options });
 
     const localStream = this.webRtcPeer.peerConnection.getLocalStreams()[0];
+    const _this = this;
     localStream.getVideoTracks()[0].onended = function () {
+      _this.webRtcPeer.peerConnection.oniceconnectionstatechange = null;
       return kurentoManager.exitScreenShare();
     };
 
@@ -367,15 +369,24 @@ Kurento.prototype.startScreensharing = function () {
       return kurentoManager.exitScreenShare();
     };
   });
+  this.webRtcPeer.peerConnection.oniceconnectionstatechange = () => {
+    if (this.webRtcPeer) {
+      const connectionState = this.webRtcPeer.peerConnection.iceConnectionState;
+      if (connectionState === 'failed' || connectionState === 'closed') {
+        this.webRtcPeer.peerConnection.oniceconnectionstatechange = null;
+        this.onFail('ICE connection failed');
+      }
+    }
+  };
 };
 
 Kurento.prototype.onIceCandidate = function (candidate, role) {
   const self = this;
-  this.logger.info("Local candidate:", {candidate});
+  this.logger.info('Local candidate:', { candidate });
 
   const message = {
     id: this.ON_ICE_CANDIDATE_MSG,
-    role: role,
+    role,
     type: this.SFU_APP,
     voiceBridge: self.voiceBridge,
     candidate,
@@ -398,13 +409,13 @@ Kurento.prototype.viewer = function () {
   if (!this.webRtcPeer) {
     const options = {
       mediaConstraints: {
-        audio: false
+        audio: false,
       },
       remoteVideo: document.getElementById(this.renderTag),
       onicecandidate: (candidate) => {
         this.onIceCandidate(candidate, this.RECV_ROLE);
-      }
-    }
+      },
+    };
 
     this.addIceServers(this.iceServers, options);
 
@@ -415,6 +426,15 @@ Kurento.prototype.viewer = function () {
 
       this.generateOffer(self.onOfferViewer.bind(self));
     });
+    self.webRtcPeer.peerConnection.oniceconnectionstatechange = () => {
+      if (this.webRtcPeer) {
+        const connectionState = this.webRtcPeer.peerConnection.iceConnectionState;
+        if (connectionState === 'failed' || connectionState === 'closed') {
+          this.webRtcPeer.peerConnection.oniceconnectionstatechange = null;
+          this.onFail('ICE connection failed');
+        }
+      }
+    };
   }
 };
 
@@ -434,15 +454,15 @@ Kurento.prototype.onOfferViewer = function (error, offerSdp) {
     sdpOffer: offerSdp,
   };
 
-  this.logger.info("onOfferViewer sending to screenshare server: ", {sdpOffer: message.sdpOffer});
+  this.logger.info('onOfferViewer sending to screenshare server: ', { sdpOffer: message.sdpOffer });
   this.sendMessage(message);
 };
 
 KurentoManager.prototype.joinAudio = function (tag) {
   this.exitAudio();
-  var obj = Object.create(Kurento.prototype);
+  const obj = Object.create(Kurento.prototype);
   Kurento.apply(obj, arguments);
-  this.kurentoAudio= obj;
+  this.kurentoAudio = obj;
   this.kurentoAudio.setAudio(tag);
 };
 
@@ -461,15 +481,15 @@ Kurento.prototype.listenOnly = function () {
       remoteVideo,
       onicecandidate : this.onListenOnlyIceCandidate.bind(this),
       mediaConstraints: {
-        audio:true,
-        video:false
-      }
-    }
+        audio: true,
+        video: false,
+      },
+    };
 
     this.addIceServers(this.iceServers, options);
 
-    self.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function(error) {
-      if(error) {
+    self.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) {
+      if (error) {
         return self.onFail(PEER_ERROR);
       }
 
@@ -479,39 +499,39 @@ Kurento.prototype.listenOnly = function () {
 };
 
 Kurento.prototype.onListenOnlyIceCandidate = function (candidate) {
-  let self = this;
-  this.logger.debug("[onListenOnlyIceCandidate]", {candidate});
+  const self = this;
+  this.logger.debug('[onListenOnlyIceCandidate]', { candidate });
 
-  var message = {
-    id : this.ON_ICE_CANDIDATE_MSG,
+  const message = {
+    id: this.ON_ICE_CANDIDATE_MSG,
     type: 'audio',
     role: 'viewer',
     voiceBridge: self.voiceBridge,
-    candidate : candidate,
-  }
+    candidate,
+  };
   this.sendMessage(message);
 };
 
 Kurento.prototype.onOfferListenOnly = function (error, offerSdp) {
-  let self = this;
-  if(error)  {
-    this.logger.error("[onOfferListenOnly]", error);
+  const self = this;
+  if (error) {
+    this.logger.error('[onOfferListenOnly]', error);
     return this.onFail(SDP_ERROR);
   }
 
-  let message = {
-    id : 'start',
+  const message = {
+    id: 'start',
     type: 'audio',
     role: 'viewer',
     voiceBridge: self.voiceBridge,
     caleeName: self.caleeName,
-    sdpOffer : offerSdp,
+    sdpOffer: offerSdp,
     userId: self.userId,
     userName: self.userName,
-    internalMeetingId: self.internalMeetingId
+    internalMeetingId: self.internalMeetingId,
   };
 
-  this.logger.debug("[onOfferListenOnly]", {message});
+  this.logger.debug('[onOfferListenOnly]', { message });
   this.sendMessage(message);
 };
 
@@ -522,7 +542,7 @@ Kurento.prototype.pauseTrack = function (message) {
   if (track) {
     track.enabled = false;
   }
-}
+};
 
 Kurento.prototype.resumeTrack = function (message) {
   const localStream = this.webRtcPeer.peerConnection.getLocalStreams()[0];
@@ -531,10 +551,10 @@ Kurento.prototype.resumeTrack = function (message) {
   if (track) {
     track.enabled = true;
   }
-}
+};
 
 Kurento.prototype.addIceServers = function (iceServers, options) {
-  this.logger.debug("Adding iceServers", iceServers);
+  this.logger.debug('Adding iceServers', iceServers);
   if (iceServers && iceServers.length > 0) {
     options.configuration = {};
     options.configuration.iceServers = iceServers;
@@ -562,14 +582,14 @@ Kurento.prototype.dispose = function () {
 
 Kurento.prototype.ping = function () {
   const message = {
-    id: 'ping'
+    id: 'ping',
   };
   this.sendMessage(message);
-}
+};
 
 Kurento.prototype.sendMessage = function (message) {
   const jsonMessage = JSON.stringify(message);
-  this.logger.info("Sending message:", {message});
+  this.logger.info('Sending message:', { message });
   this.ws.send(jsonMessage);
 };
 
@@ -638,12 +658,12 @@ window.getScreenConstraints = function (sendSource, callback) {
         { googCpuOveruseDetection: true },
         { googCpuOveruseEncodeUsage: true },
         { googCpuUnderuseThreshold: 55 },
-        { googCpuOveruseThreshold: 100},
+        { googCpuOveruseThreshold: 100 },
         { googPayloadPadding: true },
         { googScreencastMinBitrate: 600 },
         { googHighStartBitrate: true },
         { googHighBitrate: true },
-        { googVeryHighBitrate: true }
+        { googVeryHighBitrate: true },
       ];
 
       console.log('getScreenConstraints for Chrome returns => ', screenConstraints);
@@ -662,7 +682,6 @@ window.getScreenConstraints = function (sendSource, callback) {
   if (isSafari) {
     // At this time (version 11.1), Safari doesn't support screenshare.
     document.dispatchEvent(new Event('safariScreenshareNotSupported'));
-    return;
   }
 };
 
@@ -739,4 +758,4 @@ window.checkChromeExtInstalled = function (callback, chromeExtensionId) {
       callback(true);
     }
   );
-}*/
+} */
diff --git a/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js b/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js
index f266589972c617ca45545ae285d67ee46193a956..3c22b70b55a99d69445c888bd25c39d6a9c08a8a 100755
--- a/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js
+++ b/bigbluebutton-html5/imports/api/screenshare/client/bridge/kurento.js
@@ -3,6 +3,7 @@ import Auth from '/imports/ui/services/auth';
 import BridgeService from './service';
 import { fetchWebRTCMappedStunTurnServers } from '/imports/utils/fetchStunTurnServers';
 import logger from '/imports/startup/client/logger';
+import { notify } from '/imports/ui/services/notification';
 
 const SFU_CONFIG = Meteor.settings.public.kurento;
 const SFU_URL = SFU_CONFIG.wsUrl;
@@ -14,6 +15,8 @@ const SCREENSHARE_VIDEO_TAG = 'screenshareVideo';
 
 const CHROME_EXTENSION_KEY = CHROME_CUSTOM_EXTENSION_KEY === 'KEY' ? CHROME_DEFAULT_EXTENSION_KEY : CHROME_CUSTOM_EXTENSION_KEY;
 
+const ICE_CONNECTION_FAILED = 'ICE connection failed';
+
 const getUserId = () => Auth.userID;
 
 const getMeetingId = () => Auth.meetingID;
@@ -28,17 +31,17 @@ const logFunc = (type, message, options) => {
 
   const topic = options.topic || 'screenshare';
 
-  logger[type]({obj: Object.assign(options, {userId, userName, topic})}, `[${topic}] ${message}`);
+  logger[type]({ obj: Object.assign(options, { userId, userName, topic }) }, `[${topic}] ${message}`);
 };
 
 const modLogger = {
-  info: function (message, options = {}) {
+  info(message, options = {}) {
     logFunc('info', message, options);
   },
-  error: function (message, options = {}) {
+  error(message, options = {}) {
     logFunc('error', message, options);
   },
-  debug: function (message, options = {}) {
+  debug(message, options = {}) {
     logFunc('debug', message, options);
   },
   warn: (message, options = {}) => {
@@ -58,7 +61,7 @@ export default class KurentoScreenshareBridge {
       const options = {
         wsUrl: SFU_URL,
         iceServers,
-        logger: modLogger
+        logger: modLogger,
       };
 
       window.kurentoWatchVideo(
@@ -68,16 +71,16 @@ export default class KurentoScreenshareBridge {
         getMeetingId(),
         null,
         null,
-        options
+        options,
       );
-    };
+    }
   }
 
   kurentoExitVideo() {
     window.kurentoExitVideo();
   }
 
-  async kurentoShareScreen() {
+  async kurentoShareScreen(onFail) {
     let iceServers = [];
     try {
       iceServers = await fetchWebRTCMappedStunTurnServers(getSessionToken());
@@ -92,15 +95,14 @@ export default class KurentoScreenshareBridge {
         iceServers,
         logger: modLogger,
       };
-
       window.kurentoShareScreen(
         SCREENSHARE_VIDEO_TAG,
         BridgeService.getConferenceBridge(),
         getUserId(),
         getMeetingId(),
+        onFail,
         null,
-        null,
-        options
+        options,
       );
     }
   }
diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx
index b0a8150a32b7edf1dee47d9fba1ff83c47442f52..ce90a94c153c5783f6e67c2fb1f101597baed895 100644
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/container.jsx
@@ -12,7 +12,7 @@ export default withTracker(() => ({
   isUserModerator: Service.isUserModerator(),
   handleExitVideo: () => VideoService.exitVideo(),
   handleJoinVideo: () => VideoService.joinVideo(),
-  handleShareScreen: () => shareScreen(),
+  handleShareScreen: (onFail) => shareScreen(onFail),
   handleUnshareScreen: () => unshareScreen(),
   isVideoBroadcasting: isVideoBroadcasting(),
   recordSettingsList: Service.recordSettingsList(),
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 dc639ca2477380512d83621b0566bf4eeebafbb8..7329d4774cc7afead29ce78a3198c97533577952 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
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
 import { defineMessages, injectIntl, intlShape } from 'react-intl';
 import browser from 'browser-detect';
 import Button from '/imports/ui/components/button/component';
+import logger from '/imports/startup/client/logger';
+import { notify } from '/imports/ui/services/notification';
 import { styles } from '../styles';
 
 const propTypes = {
@@ -30,7 +32,10 @@ const intlMessages = defineMessages({
     id: 'app.actionsBar.actionsDropdown.stopDesktopShareDesc',
     description: 'adds context to stop desktop share option',
   },
-
+  iceConnectionStateError: {
+    id: 'app.deskshare.iceConnectionStateError',
+    description: 'Error message for ice connection state failure',
+  },
 });
 
 const BROWSER_RESULTS = browser();
@@ -39,6 +44,7 @@ const isMobileBrowser = (BROWSER_RESULTS ? BROWSER_RESULTS.mobile : false) ||
     BROWSER_RESULTS.os.includes('Android') : // mobile flag doesn't always work
     false);
 const screenSharingCheck = Meteor.settings.public.kurento.enableScreensharing;
+const ICE_CONNECTION_FAILED = 'ICE connection failed';
 
 const DesktopShare = ({
   intl,
@@ -46,8 +52,19 @@ const DesktopShare = ({
   handleUnshareScreen,
   isVideoBroadcasting,
   isUserPresenter,
-}) => (
-  (screenSharingCheck && !isMobileBrowser && isUserPresenter ?
+}) => {
+  const onFail = (error) => {
+    switch (error) {
+      case ICE_CONNECTION_FAILED:
+        kurentoExitScreenShare();
+        logger.error('Ice connection state error');
+        notify(intl.formatMessage(intlMessages.iceConnectionStateError), 'error', 'desktop');
+        break;
+      default:
+        logger.error(error || 'Default error handler');
+    }
+  };
+  return (screenSharingCheck && !isMobileBrowser && isUserPresenter ?
     <Button
       className={styles.button}
       icon={isVideoBroadcasting ? 'desktop_off' : 'desktop'}
@@ -60,11 +77,11 @@ const DesktopShare = ({
       hideLabel
       circle
       size="lg"
-      onClick={isVideoBroadcasting ? handleUnshareScreen : handleShareScreen}
+      onClick={isVideoBroadcasting ? handleUnshareScreen : () => handleShareScreen(onFail)}
       id={isVideoBroadcasting ? 'unshare-screen-button' : 'share-screen-button'}
     />
-    : null)
-);
+    : null);
+};
 
 DesktopShare.propTypes = propTypes;
 export default injectIntl(DesktopShare);
diff --git a/bigbluebutton-html5/imports/ui/components/screenshare/service.js b/bigbluebutton-html5/imports/ui/components/screenshare/service.js
index 2c423fa034b862b0511cbdd3fc7c9a9829ed2b17..99e61aae0b1506660d33dcb707793e1756b87852 100644
--- a/bigbluebutton-html5/imports/ui/components/screenshare/service.js
+++ b/bigbluebutton-html5/imports/ui/components/screenshare/service.js
@@ -33,8 +33,8 @@ const presenterScreenshareHasStarted = () => {
   KurentoBridge.kurentoWatchVideo();
 }
 
-const shareScreen = () => {
-  KurentoBridge.kurentoShareScreen();
+const shareScreen = (onFail) => {
+  KurentoBridge.kurentoShareScreen(onFail);
 }
 
 const unshareScreen = () => {
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index c06cedcfebdc36e3a79aeef9c28546d26b5f7baf..f4a01c30d4a5840d9763a1269c6cdab8c71975a8 100755
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -349,6 +349,7 @@
     "app.video.stats.rtt": "RTT",
     "app.video.stats.encodeUsagePercent": "Encode usage",
     "app.video.stats.currentDelay": "Current delay",
+    "app.deskshare.iceConnectionStateError": "Error 1108: ICE connection failed when sharing screen",
     "app.sfu.mediaServerConnectionError2000": "Error 2000: Unable to connect to media server",
     "app.sfu.mediaServerOffline2001": "Error 2001: Media server is offline. Please try again later.",
     "app.sfu.mediaServerNoResources2002": "Error 2002: Media server has no available resources",