diff --git a/src/CONST.js b/src/CONST.js
index 22a5ea8a3c82..e5ffb21bbe37 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -777,6 +777,9 @@ const CONST = {
         DELETE: 'delete',
         UPDATE: 'update',
     },
+    BRICK_ROAD_INDICATOR_STATUS: {
+        ERROR: 'error',
+    },
 };
 
 export default CONST;
diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js
index 08b3085c0be3..e4cfd785dac3 100644
--- a/src/components/MenuItem.js
+++ b/src/components/MenuItem.js
@@ -133,7 +133,7 @@ const MenuItem = props => (
                         </View>
                     )}
                     {props.brickRoadIndicator && (
-                        <View style={[[styles.alignItemsCenter, styles.justifyContentCenter]]}>
+                        <View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
                             <Icon
                                 src={Expensicons.DotIndicator}
                                 fill={props.brickRoadIndicator === 'error' ? colors.red : colors.green}
diff --git a/src/components/OfflineWithFeedback.js b/src/components/OfflineWithFeedback.js
index 2422e4745b73..9c2c5db58aa8 100644
--- a/src/components/OfflineWithFeedback.js
+++ b/src/components/OfflineWithFeedback.js
@@ -43,6 +43,10 @@ const propTypes = {
         PropTypes.arrayOf(PropTypes.object),
         PropTypes.object,
     ]),
+
+    /** Additional style object for the error row */
+    errorRowStyles: PropTypes.arrayOf(PropTypes.object),
+
     ...withLocalizePropTypes,
 };
 
@@ -50,6 +54,7 @@ const defaultProps = {
     pendingAction: null,
     errors: null,
     style: [],
+    errorRowStyles: [],
 };
 
 /**
@@ -97,7 +102,7 @@ const OfflineWithFeedback = (props) => {
                 </View>
             )}
             {hasErrors && (
-                <View style={styles.offlineFeedback.error}>
+                <View style={[styles.offlineFeedback.error, ...props.errorRowStyles]}>
                     <View style={styles.offlineFeedback.errorDot}>
                         <Icon src={Expensicons.DotIndicator} fill={colors.red} height={variables.iconSizeSmall} width={variables.iconSizeSmall} />
                     </View>
diff --git a/src/components/OptionRow.js b/src/components/OptionRow.js
index a6a75bceb48a..cadae24e801e 100644
--- a/src/components/OptionRow.js
+++ b/src/components/OptionRow.js
@@ -23,6 +23,7 @@ import SelectCircle from './SelectCircle';
 import SubscriptAvatar from './SubscriptAvatar';
 import CONST from '../CONST';
 import * as ReportUtils from '../libs/ReportUtils';
+import variables from '../styles/variables';
 
 const propTypes = {
     /** Background Color of the Option Row */
@@ -205,6 +206,16 @@ const OptionRow = (props) => {
                                     </Text>
                                 </View>
                             ) : null}
+                            {props.option.brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR && (
+                                <View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
+                                    <Icon
+                                        src={Expensicons.DotIndicator}
+                                        fill={colors.red}
+                                        height={variables.iconSizeSmall}
+                                        width={variables.iconSizeSmall}
+                                    />
+                                </View>
+                            )}
                             {props.showSelectedState && <SelectCircle isChecked={props.isSelected} />}
                         </View>
                     </View>
@@ -298,5 +309,9 @@ export default withLocalize(memo(OptionRow, (prevProps, nextProps) => {
         return false;
     }
 
+    if (prevProps.option.brickRoadIndicator !== nextProps.option.brickRoadIndicator) {
+        return false;
+    }
+
     return true;
 }));
diff --git a/src/components/optionPropTypes.js b/src/components/optionPropTypes.js
index 47af58d240cb..78dbd19b5339 100644
--- a/src/components/optionPropTypes.js
+++ b/src/components/optionPropTypes.js
@@ -1,4 +1,5 @@
 import PropTypes from 'prop-types';
+import CONST from '../CONST';
 import participantPropTypes from './participantPropTypes';
 
 export default PropTypes.shape({
@@ -49,4 +50,7 @@ export default PropTypes.shape({
 
     // Text to show for tooltip
     tooltipText: PropTypes.string,
+
+    /** If we need to show a brick road indicator or not */
+    brickRoadIndicator: PropTypes.oneOf([CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR, '']),
 });
diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js
index 61e05b4a5a9f..d793bfaaef2d 100644
--- a/src/libs/OptionsListUtils.js
+++ b/src/libs/OptionsListUtils.js
@@ -190,6 +190,21 @@ function hasReportDraftComment(report, reportsWithDraft = {}) {
         && lodashGet(reportsWithDraft, `${ONYXKEYS.COLLECTION.REPORTS_WITH_DRAFT}${report.reportID}`, false);
 }
 
+/**
+ * @param {Object} report
+ * @param {Object} reportActions
+ * @returns {String}
+ */
+function getBrickRoadIndicatorStatusForReport(report, reportActions) {
+    const reportID = lodashGet(report, 'reportID');
+    const reportsActions = lodashGet(reportActions, `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {});
+    if (_.isEmpty(reportsActions)) {
+        return '';
+    }
+
+    return _.find(reportsActions, action => !_.isEmpty(action.errors)) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : '';
+}
+
 /**
  * Creates a report list option
  *
@@ -197,12 +212,13 @@ function hasReportDraftComment(report, reportsWithDraft = {}) {
  * @param {Object} personalDetails
  * @param {Object} report
  * @param {Object} reportsWithDraft
+ * @param {Object} reportActions
  * @param {Object} options
  * @param {Boolean} [options.showChatPreviewLine]
  * @param {Boolean} [options.forcePolicyNamePreview]
  * @returns {Object}
  */
-function createOption(logins, personalDetails, report, reportsWithDraft, {
+function createOption(logins, personalDetails, report, reportsWithDraft, reportActions = {}, {
     showChatPreviewLine = false,
     forcePolicyNamePreview = false,
 }) {
@@ -252,6 +268,7 @@ function createOption(logins, personalDetails, report, reportsWithDraft, {
     return {
         text: reportName,
         alternateText,
+        brickRoadIndicator: getBrickRoadIndicatorStatusForReport(report, reportActions),
         icons: ReportUtils.getIcons(report, personalDetails, policies, lodashGet(personalDetail, ['avatar'])),
         tooltipText,
         ownerEmail: lodashGet(report, ['ownerEmail']),
@@ -345,6 +362,7 @@ function isCurrentUser(userDetails) {
  */
 function getOptions(reports, personalDetails, activeReportID, {
     reportsWithDraft = {},
+    reportActions = {},
     betas = [],
     selectedOptions = [],
     maxRecentReportsToShow = 0,
@@ -449,7 +467,7 @@ function getOptions(reports, personalDetails, activeReportID, {
             reportMapForLogins[logins[0]] = report;
         }
         const isSearchingSomeonesPolicyExpenseChat = !report.isOwnPolicyExpenseChat && searchValue !== '';
-        allReportOptions.push(createOption(logins, personalDetails, report, reportsWithDraft, {
+        allReportOptions.push(createOption(logins, personalDetails, report, reportsWithDraft, reportActions, {
             showChatPreviewLine,
             forcePolicyNamePreview: isPolicyExpenseChat ? isSearchingSomeonesPolicyExpenseChat : forcePolicyNamePreview,
         }));
@@ -460,6 +478,7 @@ function getOptions(reports, personalDetails, activeReportID, {
         personalDetails,
         reportMapForLogins[personalDetail.login],
         reportsWithDraft,
+        reportActions,
         {
             showChatPreviewLine,
             forcePolicyNamePreview,
@@ -581,7 +600,7 @@ function getOptions(reports, personalDetails, activeReportID, {
         const login = (Str.isValidPhone(searchValue) && !searchValue.includes('+'))
             ? `+${countryCodeByIP}${searchValue}`
             : searchValue;
-        userToInvite = createOption([login], personalDetails, null, reportsWithDraft, {
+        userToInvite = createOption([login], personalDetails, null, reportsWithDraft, reportActions, {
             showChatPreviewLine,
         });
         userToInvite.icons = [ReportUtils.getDefaultAvatar(login)];
@@ -744,9 +763,10 @@ function getMemberInviteOptions(
  * @param {String} priorityMode
  * @param {Array<String>} betas
  * @param {Object} reportsWithDraft
+ * @param {Object} reportActions
  * @returns {Object}
  */
-function calculateSidebarOptions(reports, personalDetails, activeReportID, priorityMode, betas, reportsWithDraft) {
+function calculateSidebarOptions(reports, personalDetails, activeReportID, priorityMode, betas, reportsWithDraft, reportActions) {
     let sideBarOptions = {
         prioritizeIOUDebts: true,
         prioritizeReportsWithDraftComments: true,
@@ -767,6 +787,7 @@ function calculateSidebarOptions(reports, personalDetails, activeReportID, prior
         prioritizePinnedReports: true,
         ...sideBarOptions,
         reportsWithDraft,
+        reportActions,
     });
 }
 
diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js
index 31384254d8a6..4abdb48a9fd7 100644
--- a/src/libs/actions/Report.js
+++ b/src/libs/actions/Report.js
@@ -59,10 +59,6 @@ const allReports = {};
 let conciergeChatReportID;
 const typingWatchTimers = {};
 
-// Map of optimistic report action IDs. These should be cleared when replaced by a recent fetch of report history
-// since we will then be up to date and any optimistic actions that are still waiting to be replaced can be removed.
-const optimisticReportActionIDs = {};
-
 /**
  * @param {Number} reportID
  * @param {Number} lastReadSequenceNumber
@@ -398,26 +394,6 @@ function setLocalIOUReportData(iouReportObject) {
     Onyx.merge(iouReportKey, iouReportObject);
 }
 
-/**
- * Remove all optimistic actions from report actions and reset the optimisticReportActionsIDs array. We do this
- * to clear any stuck optimistic actions that have not be updated for whatever reason.
- *
- * @param {Number} reportID
- */
-function removeOptimisticActions(reportID) {
-    const actionIDs = optimisticReportActionIDs[reportID] || [];
-    const actionsToRemove = _.reduce(actionIDs, (actions, actionID) => ({
-        ...actions,
-        [actionID]: null,
-    }), {});
-    Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, actionsToRemove);
-
-    // Reset the optimistic report action IDs to an empty array
-    Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {
-        optimisticReportActionIDs: [],
-    });
-}
-
 /**
  * Fetch the iouReport and persist the data to Onyx.
  *
@@ -663,10 +639,6 @@ function fetchActions(reportID) {
         reportActionsLimit: CONST.REPORT.ACTIONS.LIMIT,
     })
         .then((data) => {
-            // We must remove all optimistic actions so there will not be any stuck comments. At this point, we should
-            // be caught up and no longer need any optimistic comments.
-            removeOptimisticActions(reportID);
-
             const indexedData = _.indexBy(data.history, 'sequenceNumber');
             Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, indexedData);
         });
@@ -821,7 +793,7 @@ function buildOptimisticReportAction(reportID, text, file) {
             isFirstItem: false,
             isAttachment,
             attachmentInfo,
-            isLoading: true,
+            pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
             shouldShow: true,
         },
     };
@@ -876,19 +848,6 @@ function addActions(reportID, text = '', file) {
         lastReadSequenceNumber: newSequenceNumber,
     };
 
-    // Store the optimistic action ID on the report the comment was added to. It will be removed later when refetching
-    // report actions in order to clear out any stuck actions (i.e. actions where the client never received a Pusher
-    // event, for whatever reason, from the server with the new action data
-    optimisticReport.optimisticReportActionIDs = [...(optimisticReportActionIDs[reportID] || [])];
-
-    if (text) {
-        optimisticReport.optimisticReportActionIDs.push(reportCommentAction.clientID);
-    }
-
-    if (file) {
-        optimisticReport.optimisticReportActionIDs.push(attachmentAction.clientID);
-    }
-
     // Optimistically add the new actions to the store before waiting to save them to the server
     const optimisticReportActions = {};
     if (text) {
@@ -931,26 +890,8 @@ function addActions(reportID, text = '', file) {
         DateUtils.setTimezoneUpdated();
     }
 
-    const failureDataReportActions = {};
-    const defaultLoadingState = {
-        isLoading: false,
-    };
-
-    if (text) {
-        failureDataReportActions[reportCommentAction.clientID] = defaultLoadingState;
-    }
-
-    if (file) {
-        failureDataReportActions[attachmentAction.clientID] = defaultLoadingState;
-    }
-
     API.write(commandName, parameters, {
         optimisticData,
-        failureData: [{
-            onyxMethod: CONST.ONYX.METHOD.MERGE,
-            key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`,
-            value: failureDataReportActions,
-        }],
     });
 }
 
@@ -1247,9 +1188,6 @@ function handleReportChanged(report) {
     if (report.reportID && report.reportName === undefined) {
         fetchChatReportsByIDs([report.reportID]);
     }
-
-    // Store optimistic actions IDs for each report
-    optimisticReportActionIDs[report.reportID] = report.optimisticReportActionIDs;
 }
 
 /**
@@ -1490,7 +1428,7 @@ function viewNewReportAction(reportID, action) {
     if (isFromCurrentUser) {
         updatedReportObject.unreadActionCount = 0;
         updatedReportObject.lastVisitedTimestamp = Date.now();
-        updatedReportObject.lastReadSequenceNumber = action.sequenceNumber;
+        updatedReportObject.lastReadSequenceNumber = action.pendingAction ? lastReadSequenceNumber : action.sequenceNumber;
     } else if (incomingSequenceNumber > lastReadSequenceNumber) {
         updatedReportObject.unreadActionCount = getUnreadActionCount(reportID) + 1;
     }
diff --git a/src/libs/actions/ReportActions.js b/src/libs/actions/ReportActions.js
index 8b87ccb8480f..caed131681db 100644
--- a/src/libs/actions/ReportActions.js
+++ b/src/libs/actions/ReportActions.js
@@ -130,10 +130,21 @@ function isFromCurrentUser(reportID, sequenceNumber, currentUserAccountID, actio
     return action.actorAccountID === currentUserAccountID;
 }
 
+/**
+ * @param {Number} reportID
+ * @param {String} clientID
+ */
+function deleteClientAction(reportID, clientID) {
+    Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {
+        [clientID]: null,
+    });
+}
+
 export {
     isReportMissingActions,
     dangerouslyGetReportActionsMaxSequenceNumber,
     getDeletedCommentsCount,
     getLastVisibleMessageText,
     isFromCurrentUser,
+    deleteClientAction,
 };
diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js
index 948cac72c2e2..9d5926987242 100644
--- a/src/pages/home/report/ReportActionItem.js
+++ b/src/pages/home/report/ReportActionItem.js
@@ -31,6 +31,8 @@ import styles from '../../../styles/styles';
 import SelectionScraper from '../../../libs/SelectionScraper';
 import * as User from '../../../libs/actions/User';
 import * as ReportUtils from '../../../libs/ReportUtils';
+import OfflineWithFeedback from '../../../components/OfflineWithFeedback';
+import * as ReportActions from '../../../libs/actions/ReportActions';
 
 const propTypes = {
     /** The ID of the report this action is on. */
@@ -185,17 +187,24 @@ class ReportActionItem extends Component {
                                     (this.props.network.isOffline && this.props.action.isLoading) || this.props.action.error,
                                 )}
                             >
-                                {!this.props.displayAsGroup
-                                    ? (
-                                        <ReportActionItemSingle action={this.props.action} showHeader={!this.props.draftMessage}>
-                                            {children}
-                                        </ReportActionItemSingle>
-                                    )
-                                    : (
-                                        <ReportActionItemGrouped>
-                                            {children}
-                                        </ReportActionItemGrouped>
-                                    )}
+                                <OfflineWithFeedback
+                                    onClose={() => ReportActions.deleteClientAction(this.props.report.reportID, this.props.action.clientID)}
+                                    pendingAction={this.props.action.pendingAction}
+                                    errors={this.props.action.errors}
+                                    errorRowStyles={[styles.ml10, styles.mr2]}
+                                >
+                                    {!this.props.displayAsGroup
+                                        ? (
+                                            <ReportActionItemSingle action={this.props.action} showHeader={!this.props.draftMessage}>
+                                                {children}
+                                            </ReportActionItemSingle>
+                                        )
+                                        : (
+                                            <ReportActionItemGrouped>
+                                                {children}
+                                            </ReportActionItemGrouped>
+                                        )}
+                                </OfflineWithFeedback>
                             </View>
                             <MiniReportActionContextMenu
                                 reportID={this.props.reportID}
diff --git a/src/pages/home/sidebar/SidebarLinks.js b/src/pages/home/sidebar/SidebarLinks.js
index 4931b1f6ffdb..a9c64edc0ec0 100644
--- a/src/pages/home/sidebar/SidebarLinks.js
+++ b/src/pages/home/sidebar/SidebarLinks.js
@@ -138,6 +138,7 @@ class SidebarLinks extends React.Component {
             props.priorityMode,
             props.betas,
             props.reportsWithDraft,
+            props.reportActions,
         );
         return sidebarOptions.recentReports;
     }
@@ -371,5 +372,8 @@ export default compose(
         reportsWithDraft: {
             key: ONYXKEYS.COLLECTION.REPORTS_WITH_DRAFT,
         },
+        reportActions: {
+            key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
+        },
     }),
 )(SidebarLinks);
diff --git a/src/styles/utilities/spacing.js b/src/styles/utilities/spacing.js
index 6ba2830de7bf..246f2a0da47b 100644
--- a/src/styles/utilities/spacing.js
+++ b/src/styles/utilities/spacing.js
@@ -117,6 +117,10 @@ export default {
         marginLeft: 32,
     },
 
+    ml10: {
+        marginLeft: 40,
+    },
+
     mln5: {
         marginLeft: -20,
     },
diff --git a/tests/actions/ReportTest.js b/tests/actions/ReportTest.js
index 3955959b2d1f..697dca649066 100644
--- a/tests/actions/ReportTest.js
+++ b/tests/actions/ReportTest.js
@@ -95,13 +95,13 @@ describe('actions/Report', () => {
                 clientID = resultAction.sequenceNumber;
                 expect(resultAction.message).toEqual(REPORT_ACTION.message);
                 expect(resultAction.person).toEqual(REPORT_ACTION.person);
-                expect(resultAction.isLoading).toEqual(true);
+                expect(resultAction.pendingAction).toEqual(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
 
                 // We subscribed to the Pusher channel above and now we need to simulate a reportComment action
                 // Pusher event so we can verify that action was handled correctly and merged into the reportActions.
                 const channel = Pusher.getChannel(`${CONST.PUSHER.PRIVATE_USER_CHANNEL_PREFIX}1${CONFIG.PUSHER.SUFFIX}`);
                 const actionWithoutLoading = {...resultAction};
-                delete actionWithoutLoading.isLoading;
+                delete actionWithoutLoading.pendingAction;
                 channel.emit(Pusher.TYPE.ONYX_API_UPDATE, [
                     {
                         onyxMethod: CONST.ONYX.METHOD.MERGE,
@@ -137,7 +137,7 @@ describe('actions/Report', () => {
                 const resultAction = reportActions[ACTION_ID];
 
                 // Verify that our action is no longer in the loading state
-                expect(resultAction.isLoading).not.toBeDefined();
+                expect(resultAction.pendingAction).not.toBeDefined();
             });
     });
 
