diff --git a/src/components/ParticipantPicker.tsx b/src/components/ParticipantPicker.tsx
index 91a864c405b5..42cc0f24e27d 100644
--- a/src/components/ParticipantPicker.tsx
+++ b/src/components/ParticipantPicker.tsx
@@ -27,6 +27,9 @@ type ParticipantPickerProps = {
     /** Whether the IOU is workspaces only */
     isWorkspacesOnly?: boolean;
 
+    /** Whether to exclude P2P recipients (and the invite-by-email option) from the list. Used for negative amounts, which P2P chats don't support. */
+    shouldExcludeP2P?: boolean;
+
     /** Callback fired when participants are updated */
     onParticipantsAdded: (value: Participant[]) => void;
 
@@ -47,6 +50,7 @@ function ParticipantPicker({
     isPerDiemRequest = false,
     isTimeRequest = false,
     isWorkspacesOnly = false,
+    shouldExcludeP2P = false,
     onParticipantsAdded,
     onFinish,
     isVisible = true,
@@ -67,6 +71,7 @@ function ParticipantPicker({
             isPerDiemRequest={isPerDiemRequest}
             isTimeRequest={isTimeRequest}
             isWorkspacesOnly={isWorkspacesOnly}
+            shouldExcludeP2P={shouldExcludeP2P}
             onRestrictedParticipantSelected={onClose}
             initiallySelectedReportID={selectedParticipant?.reportID}
             shouldMoveSelectedToTop
diff --git a/src/hooks/useParticipantSubmission.ts b/src/hooks/useParticipantSubmission.ts
index 4ffc3ebba138..5a97f7608bd0 100644
--- a/src/hooks/useParticipantSubmission.ts
+++ b/src/hooks/useParticipantSubmission.ts
@@ -4,6 +4,7 @@ import {setTransactionReport} from '@libs/actions/Transaction';
 import {READ_COMMANDS} from '@libs/API/types';
 import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import HttpUtils from '@libs/HttpUtils';
+import {isParticipantP2P} from '@libs/IOUUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import {isGroupPolicy} from '@libs/PolicyUtils';
 import {findSelfDMReportID, generateReportID, isInvoiceRoomWithID} from '@libs/ReportUtils';
@@ -208,12 +209,23 @@ function useParticipantSubmission({
         });
     };
 
+    // P2P chats don't support negative amounts. When a negative amount was entered before a participant was
+    // selected (e.g. "Submit it to someone" from a self DM track expense), assigning it to a P2P participant
+    // would fail at submit, so keep the expense on the self DM as a track expense — mirroring the guard in the
+    // confirmation step's handleParticipantsAdded. This doesn't apply to an expense already bound to a policy
+    // expense chat, which must stay on that workspace.
+    const shouldKeepNegativeExpenseOnSelfDM = (firstParticipant: Participant | undefined) => {
+        const currentTransaction = dataRef.current.initialTransaction;
+        const isTransactionOnPolicyExpenseChat = currentTransaction?.participants?.some((participant) => participant?.isPolicyExpenseChat);
+        return (currentTransaction?.amount ?? 0) < 0 && !isTransactionOnPolicyExpenseChat && isParticipantP2P(firstParticipant);
+    };
+
     const addParticipant = (val: Participant[]) => {
         HttpUtils.cancelPendingRequests(READ_COMMANDS.SEARCH_FOR_REPORTS);
 
         const firstParticipant = val.at(0);
 
-        if (firstParticipant?.isSelfDM && !isSplitRequest) {
+        if ((firstParticipant?.isSelfDM || shouldKeepNegativeExpenseOnSelfDM(firstParticipant)) && !isSplitRequest) {
             trackExpense();
             return;
         }
@@ -301,6 +313,15 @@ function useParticipantSubmission({
         // (last-rendered value from dataRef) because the Onyx write from addParticipant may not have
         // caused a re-render yet by the time goToNextStep is called.
         const effectiveParticipants = nextParticipants ?? currentParticipants;
+
+        // ParticipantSearchResults.addSingleParticipant fires onFinish (this callback) right after onParticipantsAdded
+        // for any non-self row. When the negative-amount P2P fallback in addParticipant already kept the expense on the
+        // self DM as a track expense (and queued that navigation), skip the submit navigation here so it doesn't
+        // override the track flow and land the user on a submit confirmation for the self-DM draft.
+        if (!isSplitRequest && shouldKeepNegativeExpenseOnSelfDM(effectiveParticipants?.at(0))) {
+            return;
+        }
+
         const isPolicyExpenseChat = effectiveParticipants?.some((participant) => participant.isPolicyExpenseChat);
         if (iouType === CONST.IOU.TYPE.SPLIT && !isPolicyExpenseChat && splitTransaction?.amount && splitTransaction?.currency) {
             const participantAccountIDs = effectiveParticipants?.map((participant) => participant.accountID) as number[];
diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx
index 325d2d7949aa..7660258ce05d 100644
--- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx
+++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx
@@ -35,6 +35,9 @@ type MoneyRequestParticipantsSelectorProps = {
     /** Whether this is a transaction from a credit card import */
     isTransactionFromCreditCardImport?: boolean;
 
+    /** Whether to exclude P2P recipients (and the invite-by-email option) from the list. Used for negative amounts, which P2P chats don't support. */
+    shouldExcludeP2P?: boolean;
+
     /** Report ID of a pre-selected participant whose selection state can't be derived from the participants array (e.g. self DM with accountID 0) */
     initiallySelectedReportID?: string;
 
@@ -63,6 +66,7 @@ function MoneyRequestParticipantsSelector({
     isTimeRequest = false,
     isWorkspacesOnly = false,
     isTransactionFromCreditCardImport = false,
+    shouldExcludeP2P = false,
     initiallySelectedReportID,
     shouldMoveSelectedToTop = false,
     onRestrictedParticipantSelected,
@@ -92,6 +96,7 @@ function MoneyRequestParticipantsSelector({
             isTimeRequest={isTimeRequest}
             isNative={isNative}
             isTransactionFromCreditCardImport={isTransactionFromCreditCardImport}
+            shouldExcludeP2P={shouldExcludeP2P}
             selectionListRef={selectionListRef}
             textInputAutoFocus={textInputAutoFocus}
             setTextInputAutoFocus={setTextInputAutoFocus}
diff --git a/src/pages/iou/request/ParticipantSearchResults.tsx b/src/pages/iou/request/ParticipantSearchResults.tsx
index 997abdceacd4..c9ab2f18ce7c 100644
--- a/src/pages/iou/request/ParticipantSearchResults.tsx
+++ b/src/pages/iou/request/ParticipantSearchResults.tsx
@@ -78,6 +78,9 @@ type ParticipantSearchResultsProps = {
     /** Whether this is a transaction from a credit card import */
     isTransactionFromCreditCardImport: boolean;
 
+    /** Whether to exclude P2P recipients (and the invite-by-email option) from the list. Used for negative amounts, which P2P chats don't support. */
+    shouldExcludeP2P?: boolean;
+
     /** Forwarded ref for the SelectionList — used by the parent's useImperativeHandle */
     selectionListRef: Ref<SelectionListWithSectionsHandle | null>;
 
@@ -112,6 +115,7 @@ function ParticipantSearchResults({
     isTimeRequest,
     isNative,
     isTransactionFromCreditCardImport,
+    shouldExcludeP2P = false,
     selectionListRef,
     textInputAutoFocus,
     setTextInputAutoFocus,
@@ -166,7 +170,7 @@ function ParticipantSearchResults({
         excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
         includeOwnedWorkspaceChats: iouType === CONST.IOU.TYPE.SUBMIT || iouType === CONST.IOU.TYPE.CREATE || iouType === CONST.IOU.TYPE.SPLIT || iouType === CONST.IOU.TYPE.TRACK,
         excludeNonAdminWorkspaces: action === CONST.IOU.ACTION.SHARE,
-        includeP2P: !isCategorizeOrShareAction && !isPerDiemRequest && !isTimeRequest && !isTransactionFromCreditCardImport,
+        includeP2P: !isCategorizeOrShareAction && !isPerDiemRequest && !isTimeRequest && !isTransactionFromCreditCardImport && !shouldExcludeP2P,
         includeInvoiceRooms: iouType === CONST.IOU.TYPE.INVOICE,
         action,
         shouldSeparateSelfDMChat: iouType !== CONST.IOU.TYPE.INVOICE,
@@ -217,7 +221,7 @@ function ParticipantSearchResults({
     const {searchTerm, debouncedSearchTerm, setSearchTerm, availableOptions, selectedOptions, toggleSelection, areOptionsInitialized, onListEndReached, contactState} = useSearchSelector({
         selectionMode: isIOUSplit ? CONST.SEARCH_SELECTOR.SELECTION_MODE_MULTI : CONST.SEARCH_SELECTOR.SELECTION_MODE_SINGLE,
         searchContext: CONST.SEARCH_SELECTOR.SEARCH_CONTEXT_GENERAL,
-        includeUserToInvite: !isCategorizeOrShareAction && !isPerDiemRequest && !isTimeRequest && !isTransactionFromCreditCardImport,
+        includeUserToInvite: !isCategorizeOrShareAction && !isPerDiemRequest && !isTimeRequest && !isTransactionFromCreditCardImport && !shouldExcludeP2P,
         excludeLogins: CONST.EXPENSIFY_EMAILS_OBJECT,
         includeRecentReports: true,
         maxRecentReportsToShow: CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW,
diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx
index 72afa59cd25f..6cd0980a5ae0 100644
--- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx
+++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx
@@ -41,6 +41,7 @@ import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {
     getIsWorkspacesOnlyForTransaction,
     isMovingTransactionFromTrackExpense as isMovingTransactionFromTrackExpenseIOUUtils,
+    isParticipantP2P,
     navigateToStartMoneyRequestStep,
     resolveOptimisticChatReportID,
     resolveReportForMoneyRequest,
@@ -312,7 +313,17 @@ function IOURequestStepConfirmation({
             if (!activeTransactionID) {
                 return;
             }
-            if (participantsList.at(0)?.isSelfDM) {
+            const selectedParticipant = participantsList.at(0);
+            // P2P chats don't support negative amounts. When a negative amount was entered before a participant
+            // was selected (e.g. "Submit it to someone" from a self DM), assigning it to a P2P participant would
+            // fail at submit, so keep the expense on the self DM (its default) instead of assigning the P2P
+            // participant, stopping the user at selection rather than at submit. This only applies while the
+            // expense is still on the self DM — a negative expense already bound to a policy expense chat (e.g.
+            // global create auto-assigned the default workspace) must stay on that workspace rather than being
+            // silently converted into a personal track expense.
+            const isTransactionOnPolicyExpenseChat = transaction?.participants?.some((participant) => participant?.isPolicyExpenseChat);
+            const shouldKeepOnSelfDM = !!selectedParticipant?.isSelfDM || ((transaction?.amount ?? 0) < 0 && !isTransactionOnPolicyExpenseChat && isParticipantP2P(selectedParticipant));
+            if (shouldKeepOnSelfDM) {
                 setMoneyRequestParticipantsFromReport(activeTransactionID, selfDMReport, currentUserPersonalDetails.accountID);
                 setTransactionReport(activeTransactionID, {reportID: CONST.REPORT.UNREPORTED_REPORT_ID}, true);
                 navigation.setParams({iouType: CONST.IOU.TYPE.TRACK});
@@ -330,7 +341,7 @@ function IOURequestStepConfirmation({
                 closeParticipantPicker();
             }
         },
-        [activeTransactionID, closeParticipantPicker, currentUserPersonalDetails.accountID, navigation, selfDMReport, iouType, reportID],
+        [activeTransactionID, closeParticipantPicker, currentUserPersonalDetails.accountID, navigation, selfDMReport, iouType, transaction?.amount, transaction?.participants, reportID],
     );
 
     useEffect(() => {
@@ -902,6 +913,7 @@ function IOURequestStepConfirmation({
                             isPerDiemRequest={isPerDiemRequest}
                             isTimeRequest={isTimeRequest}
                             isWorkspacesOnly={getIsWorkspacesOnlyForTransaction(transaction, requestType)}
+                            shouldExcludeP2P={(transaction?.amount ?? 0) < 0}
                             onParticipantsAdded={handleParticipantsAdded}
                             onFinish={closeParticipantPicker}
                             isVisible={isParticipantPickerVisible}
diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx
index 8c53277b0837..618288471b78 100644
--- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx
+++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx
@@ -149,6 +149,7 @@ function IOURequestStepParticipants({
                 isTimeRequest={isTime}
                 isWorkspacesOnly={isWorkspacesOnly}
                 isTransactionFromCreditCardImport={isTransactionFromCreditCardImport}
+                shouldExcludeP2P={(initialTransaction?.amount ?? 0) < 0}
                 initiallySelectedReportID={selectedParticipant?.reportID}
                 shouldMoveSelectedToTop
             />
