From 1775cc28169e5663829019d6413ee4a1f6e5d890 Mon Sep 17 00:00:00 2001
From: "thelullabyy (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 9 Jul 2026 23:51:25 +0000
Subject: [PATCH 1/3] Fix: keep optimistic reportID coherent for brand-new P2P
 distance recipient

Co-authored-by: thelullabyy <thelullabyy@users.noreply.github.com>
---
 src/libs/actions/IOU/Split.ts                             | 4 ++++
 .../iou/request/step/confirmation/useExpenseSubmission.ts | 8 ++++++++
 2 files changed, 12 insertions(+)

diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts
index 09941faf3f25..1ea8b3048874 100644
--- a/src/libs/actions/IOU/Split.ts
+++ b/src/libs/actions/IOU/Split.ts
@@ -142,6 +142,8 @@ type CreateDistanceRequestInformation = {
     shouldDeferAutoSubmit?: boolean;
     previousOdometerDraft?: OnyxEntry<OnyxTypes.OdometerDraft>;
     delegateAccountID: number | undefined;
+    /** Optimistic chat reportID to build the new chat report at, so it matches the ID the confirmation screen already subscribed to (brand-new P2P recipient). */
+    optimisticChatReportID?: string;
 };
 
 type CreateSplitsTransactionParams = Omit<BaseTransactionParams, 'customUnitRateID'> & {
@@ -1933,6 +1935,7 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest
         shouldDeferAutoSubmit,
         previousOdometerDraft,
         delegateAccountID,
+        optimisticChatReportID,
     } = distanceRequestInformation;
     const {policy, policyCategories, policyTagList, policyRecentlyUsedCategories, policyRecentlyUsedTags} = policyParams;
     const parsedComment = getParsedComment(transactionParams.comment);
@@ -2116,6 +2119,7 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest
             betas,
             optimisticReportPreviewActionID,
             delegateAccountID,
+            optimisticChatReportID,
         });
 
         onyxData = moneyRequestOnyxData;
diff --git a/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts b/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
index 3a7a2107de51..6e86724a22e8 100644
--- a/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
+++ b/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
@@ -732,9 +732,17 @@ function useExpenseSubmission(params: UseExpenseSubmissionParams) {
             return;
         }
 
+        // For a brand-new P2P recipient (no existing chat), the confirmation screen has already committed the draft
+        // transaction to a freshly generated optimistic reportID via setTransactionReport. Build the optimistic chat
+        // report at that same ID so the report the screen subscribes to is the one that actually gets created.
+        // Otherwise the builder mints a different ID and the screen hangs waiting on a report that never materializes.
+        const isBrandNewP2PRecipient = !report && !participant.isPolicyExpenseChat && !participant.reportID;
+        const optimisticChatReportID = isBrandNewP2PRecipient && !!transaction.reportID && transaction.reportID !== CONST.REPORT.UNREPORTED_REPORT_ID ? transaction.reportID : undefined;
+
         const {chatReportID: distanceChatReportID, transactionID: distanceTransactionID} = createDistanceRequestIOUActions({
             report,
             participants: selectedParticipantsForRequest,
+            optimisticChatReportID,
             currentUserLogin: currentUserPersonalDetails.login ?? '',
             currentUserAccountID: currentUserPersonalDetails.accountID,
             iouType,

From 1cea8fcd631131046de9c91e8e7ef982d3c63c5b Mon Sep 17 00:00:00 2001
From: "thelullabyy (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 9 Jul 2026 23:56:44 +0000
Subject: [PATCH 2/3] Add regression test: distance createDistanceRequest
 honors optimisticChatReportID

Co-authored-by: thelullabyy <thelullabyy@users.noreply.github.com>
---
 tests/actions/IOUTest/SplitTest.ts | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/tests/actions/IOUTest/SplitTest.ts b/tests/actions/IOUTest/SplitTest.ts
index 98471a7be180..0be3e0dee30b 100644
--- a/tests/actions/IOUTest/SplitTest.ts
+++ b/tests/actions/IOUTest/SplitTest.ts
@@ -7546,6 +7546,21 @@ describe('createDistanceRequest', () => {
         expect(result.transactionID).toBeTruthy();
     });
 
+    it('builds the optimistic chat report at the provided optimisticChatReportID for a brand-new P2P recipient — so it matches the id the confirmation screen already subscribed to', async () => {
+        const recentWaypoints = (await getOnyxValue(ONYXKEYS.NVP_RECENT_WAYPOINTS)) ?? [];
+        // The confirmation screen commits the draft transaction to this generated id before submit. The action must
+        // create the optimistic chat at the same id, otherwise the screen hangs waiting on a report that never exists.
+        const optimisticChatReportID = '987654321';
+
+        const result = createDistanceRequest({
+            ...getDefaultDistanceRequestParams(undefined, {amount: 1000}, recentWaypoints),
+            participants: [{accountID: CARLOS_ACCOUNT_ID, login: CARLOS_EMAIL}],
+            optimisticChatReportID,
+        });
+
+        expect(result.chatReportID).toBe(optimisticChatReportID);
+    });
+
     it('returns chatReportID with a null iouReport for a split distance request — the UI can only navigate via chatReportID', async () => {
         const recentWaypoints = (await getOnyxValue(ONYXKEYS.NVP_RECENT_WAYPOINTS)) ?? [];
 

From ba79b7d9de38510a696b642a609a8db64f9de028 Mon Sep 17 00:00:00 2001
From: "thelullabyy (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Mon, 13 Jul 2026 17:03:43 +0000
Subject: [PATCH 3/3] Apply review suggestions: add blank line before doc
 comment per style guide

Co-authored-by: thelullabyy <thelullabyy@users.noreply.github.com>
---
 src/libs/actions/IOU/Split.ts      | 1 +
 tests/actions/IOUTest/SplitTest.ts | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts
index 1ea8b3048874..9eb2d0243672 100644
--- a/src/libs/actions/IOU/Split.ts
+++ b/src/libs/actions/IOU/Split.ts
@@ -142,6 +142,7 @@ type CreateDistanceRequestInformation = {
     shouldDeferAutoSubmit?: boolean;
     previousOdometerDraft?: OnyxEntry<OnyxTypes.OdometerDraft>;
     delegateAccountID: number | undefined;
+
     /** Optimistic chat reportID to build the new chat report at, so it matches the ID the confirmation screen already subscribed to (brand-new P2P recipient). */
     optimisticChatReportID?: string;
 };
diff --git a/tests/actions/IOUTest/SplitTest.ts b/tests/actions/IOUTest/SplitTest.ts
index 0a950f7c73f9..4e6e24192554 100644
--- a/tests/actions/IOUTest/SplitTest.ts
+++ b/tests/actions/IOUTest/SplitTest.ts
@@ -7548,6 +7548,7 @@ describe('createDistanceRequest', () => {
 
     it('builds the optimistic chat report at the provided optimisticChatReportID for a brand-new P2P recipient — so it matches the id the confirmation screen already subscribed to', async () => {
         const recentWaypoints = (await getOnyxValue(ONYXKEYS.NVP_RECENT_WAYPOINTS)) ?? [];
+
         // The confirmation screen commits the draft transaction to this generated id before submit. The action must
         // create the optimistic chat at the same id, otherwise the screen hangs waiting on a report that never exists.
         const optimisticChatReportID = '987654321';
