diff --git a/ui/component/app/index.js b/ui/component/app/index.js
index 2802bbd2f..db2a7ec2f 100644
--- a/ui/component/app/index.js
+++ b/ui/component/app/index.js
@@ -21,6 +21,7 @@ import {
   selectAutoUpdateDownloaded,
   selectModal,
   selectActiveChannelClaim,
+  selectIsReloadRequired,
 } from 'redux/selectors/app';
 import { doGetWalletSyncPreference, doSetLanguage, doSetHomepage } from 'redux/actions/settings';
 import { doSyncLoop } from 'redux/actions/sync';
@@ -44,6 +45,7 @@ const select = (state) => ({
   languages: selectLoadedLanguages(state),
   autoUpdateDownloaded: selectAutoUpdateDownloaded(state),
   isUpgradeAvailable: selectIsUpgradeAvailable(state),
+  isReloadRequired: selectIsReloadRequired(state),
   syncError: selectGetSyncErrorMessage(state),
   uploadCount: selectUploadCount(state),
   rewards: selectUnclaimedRewards(state),
diff --git a/ui/component/app/view.jsx b/ui/component/app/view.jsx
index 68604f599..e42b76f05 100644
--- a/ui/component/app/view.jsx
+++ b/ui/component/app/view.jsx
@@ -6,6 +6,7 @@ import classnames from 'classnames';
 import analytics from 'analytics';
 import { buildURI, parseURI } from 'util/lbryURI';
 import { SIMPLE_SITE } from 'config';
+import Nag from 'component/common/nag';
 import Router from 'component/router/index';
 import ReactModal from 'react-modal';
 import { openContextMenu } from 'util/context-menu';
@@ -17,10 +18,12 @@ import REWARDS from 'rewards';
 import usePersistedState from 'effects/use-persisted-state';
 import Spinner from 'component/spinner';
 import LANGUAGES from 'constants/languages';
+
 // @if TARGET='app'
 import useZoom from 'effects/use-zoom';
 import useHistoryNav from 'effects/use-history-nav';
 // @endif
+
 // @if TARGET='web'
 import {
   useDegradedPerformance,
@@ -30,11 +33,11 @@ import {
   STATUS_DOWN,
 } from 'web/effects/use-degraded-performance';
 // @endif
+
 import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
 
 const FileDrop = lazyImport(() => import('component/fileDrop' /* webpackChunkName: "secondary" */));
 const ModalRouter = lazyImport(() => import('modal/modalRouter' /* webpackChunkName: "secondary" */));
-const Nag = lazyImport(() => import('component/common/nag' /* webpackChunkName: "secondary" */));
 const NagContinueFirstRun = lazyImport(() =>
   import('component/nagContinueFirstRun' /* webpackChunkName: "secondary" */)
 );
@@ -92,6 +95,7 @@ type Props = {
   setLanguage: (string) => void,
   doSetHomepage: (string) => void,
   isUpgradeAvailable: boolean,
+  isReloadRequired: boolean,
   autoUpdateDownloaded: boolean,
   updatePreferences: () => Promise<any>,
   getWalletSyncPref: () => Promise<any>,
@@ -126,6 +130,7 @@ function App(props: Props) {
     signIn,
     autoUpdateDownloaded,
     isUpgradeAvailable,
+    isReloadRequired,
     requestDownloadUpgrade,
     uploadCount,
     history,
@@ -502,6 +507,14 @@ function App(props: Props) {
             {user === null && <NagNoUser />}
             {/* @endif */}
           </React.Suspense>
+
+          {isReloadRequired && (
+            <Nag
+              message={__('A new version of Odysee is available.')}
+              actionText={__('Refresh')}
+              onClick={() => window.location.reload()}
+            />
+          )}
         </React.Fragment>
       )}
     </div>
diff --git a/ui/constants/action_types.js b/ui/constants/action_types.js
index 249d28d7a..06c5ed663 100644
--- a/ui/constants/action_types.js
+++ b/ui/constants/action_types.js
@@ -32,6 +32,7 @@ export const TOGGLE_YOUTUBE_SYNC_INTEREST = 'TOGGLE_YOUTUBE_SYNC_INTEREST';
 export const TOGGLE_SPLASH_ANIMATION = 'TOGGLE_SPLASH_ANIMATION';
 export const SET_ACTIVE_CHANNEL = 'SET_ACTIVE_CHANNEL';
 export const SET_INCOGNITO = 'SET_INCOGNITO';
+export const RELOAD_REQUIRED = 'RELOAD_REQUIRED';
 
 // Navigation
 export const CHANGE_AFTER_AUTH_PATH = 'CHANGE_AFTER_AUTH_PATH';
diff --git a/ui/redux/reducers/app.js b/ui/redux/reducers/app.js
index 4772ebb2d..c7abe855b 100644
--- a/ui/redux/reducers/app.js
+++ b/ui/redux/reducers/app.js
@@ -34,6 +34,7 @@ export type AppState = {
   checkUpgradeTimer: ?number,
   isUpgradeAvailable: ?boolean,
   isUpgradeSkipped: ?boolean,
+  isReloadRequired: ?boolean,
   hasClickedComment: boolean,
   enhancedLayout: boolean,
   splashAnimationEnabled: boolean,
@@ -71,6 +72,7 @@ const defaultState: AppState = {
   checkUpgradeTimer: undefined,
   isUpgradeAvailable: undefined,
   isUpgradeSkipped: undefined,
+  isReloadRequired: undefined,
   enhancedLayout: false,
   splashAnimationEnabled: true,
   searchOptionsExpanded: false,
@@ -213,6 +215,11 @@ reducers[ACTIONS.UPGRADE_DOWNLOAD_PROGRESSED] = (state, action) =>
     downloadProgress: action.data.percent,
   });
 
+reducers[ACTIONS.RELOAD_REQUIRED] = (state, action) =>
+  Object.assign({}, state, {
+    isReloadRequired: true,
+  });
+
 reducers[ACTIONS.DOWNLOADING_COMPLETED] = (state) => {
   const { badgeNumber } = state;
 
diff --git a/ui/redux/selectors/app.js b/ui/redux/selectors/app.js
index 59f2e80d8..923556e72 100644
--- a/ui/redux/selectors/app.js
+++ b/ui/redux/selectors/app.js
@@ -21,6 +21,7 @@ export const selectUpdateUrl = createSelector(selectPlatform, (platform) => {
 export const selectHasClickedComment = (state) => selectState(state).hasClickedComment;
 export const selectRemoteVersion = (state) => selectState(state).remoteVersion;
 export const selectIsUpgradeAvailable = (state) => selectState(state).isUpgradeAvailable;
+export const selectIsReloadRequired = (state) => selectState(state).isReloadRequired;
 
 export const selectUpgradeFilename = createSelector(selectPlatform, selectRemoteVersion, (platform, version) => {
   switch (platform) {
diff --git a/ui/util/lazyImport.js b/ui/util/lazyImport.js
index da3e64b04..597fa67c8 100644
--- a/ui/util/lazyImport.js
+++ b/ui/util/lazyImport.js
@@ -1,34 +1,26 @@
 import React from 'react';
+import * as ACTIONS from 'constants/action_types';
 
-let localStorageAvailable;
-try {
-  localStorageAvailable = Boolean(window.localStorage);
-} catch (e) {
-  localStorageAvailable = false;
+const RETRY_DELAY_MS = 2000;
+const RETRY_ATTEMPTS = 2;
+
+function componentLoader(lazyComponent, attemptsLeft) {
+  return new Promise((resolve, reject) => {
+    lazyComponent()
+      .then(resolve)
+      .catch((error) => {
+        setTimeout(() => {
+          if (attemptsLeft === 1) {
+            window.store.dispatch({ type: ACTIONS.RELOAD_REQUIRED });
+            console.error(error.message); // Spew the error so users can report to us if reloading doesn't help.
+          } else {
+            componentLoader(lazyComponent, attemptsLeft - 1).then(resolve, reject);
+          }
+        }, RETRY_DELAY_MS);
+      });
+  });
 }
 
-export const lazyImport = (componentImport) =>
-  React.lazy(async () => {
-    const pageHasAlreadyBeenForceRefreshed = localStorageAvailable
-      ? JSON.parse(window.localStorage.getItem('page-has-been-force-refreshed') || 'false')
-      : false;
-
-    try {
-      const component = await componentImport();
-      if (localStorageAvailable) {
-        window.localStorage.setItem('page-has-been-force-refreshed', 'false');
-      }
-      return component;
-    } catch (error) {
-      if (!pageHasAlreadyBeenForceRefreshed) {
-        // It's highly likely that the user's session is old. Try reloading once.
-        if (localStorageAvailable) {
-          window.localStorage.setItem('page-has-been-force-refreshed', 'true');
-        }
-        return window.location.reload();
-      }
-
-      // If it still didn't work, then relay the error.
-      throw error;
-    }
-  });
+export function lazyImport(componentImport) {
+  return React.lazy(() => componentLoader(componentImport, RETRY_ATTEMPTS));
+}