diff --git a/lib/reducers/entry-reducer.js b/lib/reducers/entry-reducer.js
--- a/lib/reducers/entry-reducer.js
+++ b/lib/reducers/entry-reducer.js
@@ -74,6 +74,7 @@
 import { getConfig } from '../utils/config.js';
 import { dateString } from '../utils/date-utils.js';
 import { values } from '../utils/objects.js';
+import { generateReportID } from '../utils/report-utils.js';
 import { sanitizeActionSecrets } from '../utils/sanitization.js';
 
 function daysToEntriesFromEntryInfos(
@@ -698,6 +699,7 @@
       pushResult: afterStateCheck,
       lastActions: actionLogger.interestingActionSummaries,
       time: Date.now(),
+      id: generateReportID(),
     },
   ];
 }
diff --git a/lib/reducers/thread-reducer.js b/lib/reducers/thread-reducer.js
--- a/lib/reducers/thread-reducer.js
+++ b/lib/reducers/thread-reducer.js
@@ -51,6 +51,7 @@
 import { actionLogger } from '../utils/action-logger.js';
 import { setNewSessionActionType } from '../utils/action-utils.js';
 import { getConfig } from '../utils/config.js';
+import { generateReportID } from '../utils/report-utils.js';
 import { sanitizeActionSecrets } from '../utils/sanitization.js';
 
 function generateOpsForThreadUpdates(
@@ -145,6 +146,7 @@
       pushResult: afterStateCheck,
       lastActions: actionLogger.interestingActionSummaries,
       time: Date.now(),
+      id: generateReportID(),
     },
   ];
 }
diff --git a/lib/reducers/user-reducer.js b/lib/reducers/user-reducer.js
--- a/lib/reducers/user-reducer.js
+++ b/lib/reducers/user-reducer.js
@@ -39,6 +39,7 @@
 import { actionLogger } from '../utils/action-logger.js';
 import { setNewSessionActionType } from '../utils/action-utils.js';
 import { getConfig } from '../utils/config.js';
+import { generateReportID } from '../utils/report-utils.js';
 import { sanitizeActionSecrets } from '../utils/sanitization.js';
 
 function reduceCurrentUserInfo(
@@ -141,6 +142,7 @@
       afterStateCheck,
       lastActions: actionLogger.interestingActionSummaries,
       time: Date.now(),
+      id: generateReportID(),
     },
   ];
 }
diff --git a/lib/shared/report-utils.js b/lib/shared/report-utils.js
--- a/lib/shared/report-utils.js
+++ b/lib/shared/report-utils.js
@@ -10,6 +10,7 @@
   type ClientInconsistencyResponse,
   serverRequestTypes,
 } from '../types/request-types.js';
+import { generateReportID } from '../utils/report-utils.js';
 
 function inconsistencyResponsesToReports(
   responses: $ReadOnlyArray<ClientInconsistencyResponse>,
@@ -19,10 +20,18 @@
   return responses.map(response => {
     if (response.type === serverRequestTypes.THREAD_INCONSISTENCY) {
       const { type, ...rest } = response;
-      return { ...rest, type: reportTypes.THREAD_INCONSISTENCY };
+      return {
+        ...rest,
+        type: reportTypes.THREAD_INCONSISTENCY,
+        id: generateReportID(),
+      };
     } else if (response.type === serverRequestTypes.ENTRY_INCONSISTENCY) {
       const { type, ...rest } = response;
-      return { ...rest, type: reportTypes.ENTRY_INCONSISTENCY };
+      return {
+        ...rest,
+        type: reportTypes.ENTRY_INCONSISTENCY,
+        id: generateReportID(),
+      };
     } else {
       invariant(false, `unexpected serverRequestType ${response.type}`);
     }
diff --git a/lib/utils/report-utils.js b/lib/utils/report-utils.js
--- a/lib/utils/report-utils.js
+++ b/lib/utils/report-utils.js
@@ -1,6 +1,7 @@
 // @flow
 
 import { useSelector } from './redux-utils.js';
+import { getUUID } from './uuid.js';
 import {
   type SupportedReports,
   type EnabledReports,
@@ -26,4 +27,8 @@
   );
 }
 
-export { useIsReportEnabled, isReportEnabled };
+function generateReportID(): string {
+  return getUUID();
+}
+
+export { useIsReportEnabled, isReportEnabled, generateReportID };
diff --git a/native/crash.react.js b/native/crash.react.js
--- a/native/crash.react.js
+++ b/native/crash.react.js
@@ -34,7 +34,10 @@
   useServerCall,
   useDispatchActionPromise,
 } from 'lib/utils/action-utils.js';
-import { useIsReportEnabled } from 'lib/utils/report-utils.js';
+import {
+  generateReportID,
+  useIsReportEnabled,
+} from 'lib/utils/report-utils.js';
 import {
   sanitizeReduxReport,
   type ReduxCrashReport,
@@ -172,6 +175,7 @@
         componentStack: data.info && data.info.componentStack,
       })),
       ...sanitizedReduxReport,
+      id: generateReportID(),
     });
     this.setState({
       errorReportID: result.id,
diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js
--- a/native/input/input-state-container.react.js
+++ b/native/input/input-state-container.react.js
@@ -99,7 +99,10 @@
 import { getConfig } from 'lib/utils/config.js';
 import { getMessageForException, cloneError } from 'lib/utils/errors.js';
 import { values } from 'lib/utils/objects.js';
-import { useIsReportEnabled } from 'lib/utils/report-utils.js';
+import {
+  generateReportID,
+  useIsReportEnabled,
+} from 'lib/utils/report-utils.js';
 
 import {
   type EditInputBarMessageParameters,
@@ -1391,6 +1394,7 @@
       uploadServerID: ids.serverID,
       uploadLocalID: ids.localID,
       messageLocalID: ids.localMessageID,
+      id: generateReportID(),
     };
     this.props.dispatch({
       type: queueReportsActionType,
diff --git a/native/media/save-media.js b/native/media/save-media.js
--- a/native/media/save-media.js
+++ b/native/media/save-media.js
@@ -22,7 +22,10 @@
 import { getConfig } from 'lib/utils/config.js';
 import { getMessageForException } from 'lib/utils/errors.js';
 import { promiseAll } from 'lib/utils/promises.js';
-import { useIsReportEnabled } from 'lib/utils/report-utils.js';
+import {
+  generateReportID,
+  useIsReportEnabled,
+} from 'lib/utils/report-utils.js';
 
 import { fetchBlob } from './blob-utils.js';
 import {
@@ -110,6 +113,7 @@
         uploadLocalID: uploadIDIsLocal ? uploadID : undefined,
         messageServerID,
         messageLocalID,
+        id: generateReportID(),
       };
       dispatch({
         type: queueReportsActionType,
diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js
--- a/web/input/input-state-container.react.js
+++ b/web/input/input-state-container.react.js
@@ -96,6 +96,7 @@
 import type { CallServerEndpointOptions } from 'lib/utils/call-server-endpoint.js';
 import { getConfig } from 'lib/utils/config.js';
 import { getMessageForException, cloneError } from 'lib/utils/errors.js';
+import { generateReportID } from 'lib/utils/report-utils.js';
 
 import {
   type PendingMultimediaUpload,
@@ -1253,6 +1254,7 @@
         uploadServerID,
         uploadLocalID,
         messageLocalID,
+        id: generateReportID(),
       }),
     );
     this.props.dispatch({ type: queueReportsActionType, payload: { reports } });