You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Expense - "Allow location access" modal shows up when creating manual expense with 0 amount #85158
Version Number: 9.3.37-0 Reproducible in staging?: Yes Reproducible in production?: No If this was caught during regression testing, add the test name, ID and link from BrowserStack:#83354 Email or phone of affected tester (no customers):soidjsodijsodjnsoidjs@gmail.com Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Mac 26.2 / Chrome App Component: Money Requests
Action Performed:
Precondition:
Location access is not allowed.
Go to staging.new.expensify.com
Create a new account.
Create a workspace.
Go to workspace chat.
Click + > Create expense > Manual.
Enter 0 > Next.
On confirm page, enter Merchant.
Click Create expense.
Expected Result:
"Allow location access" modal will not show up because the expense is a manual expense.
Actual Result:
"Allow location access" modal shows up when creating manual expense with 0 amount.
Classification: Frontend bug Causing PR: #83354 - "Pass locationPermissionGranted=true when permission was already grant..." by @MobileMage (High confidence) Related Issues: #81184 (original issue that PR 83354 was fixing)
Recommendation: REVERT
PR #83354 should be reverted. While it successfully fixed the original issue (scanned receipts not collecting GPS for currency detection), it introduced a regression where manual expenses with 0 amount now incorrectly trigger the location permission modal.
Labels: Keeping DeployBlockerCash - this is an App bug that requires reverting an App PR. Removing DeployBlocker as this is not a backend issue.
Detailed Analysis
Evidence
PR #83354 modified src/pages/iou/request/step/IOURequestStepScan/useReceiptScan.ts to pass locationPermissionGranted=true when:
This condition checks for 0 amount expenses but does NOT distinguish between:
Scanned receipts (which need GPS to determine currency from location)
Manual expenses (which do not need GPS)
Verification
From the issue reproduction steps:
Create a manual expense (not scanned)
Enter amount 0
The location permission modal incorrectly appears
The fix applies to lines 234-246 in processReceipts() and lines 254-263 in submitReceipts() in useReceiptScan.ts, where the GPS requirement logic does not check the expense type.
Root Cause
The PR correctly identified that scanned receipts with 0 amount need GPS coordinates for currency detection when permission is already granted. However, the implementation applies this logic to ALL expenses with 0 amount, including manual expenses that should never trigger location permission flows.
The same issue exists in IOURequestStepConfirmation.tsx line 285:
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
Identify the pull request that introduced this issue and revert it.
Please re-state the problem that we are trying to solve in this issue.
When creating a manual expense with 0 amount (+ > Create expense > Manual > Enter 0 > Next > Confirm), the "Allow location access" modal incorrectly appears. This modal should only appear for scanned receipts that need GPS coordinates to determine currency from location — never for manual expenses.
What is the root cause of that problem?
The gpsRequired condition in IOURequestStepConfirmation.tsx:285 uses transaction.amount === 0 as a proxy for "this is a scanned receipt needing GPS," but manual expenses can also have amount=0:
The condition relies on Object.values(receiptFiles).length being truthy to filter out non-receipt expenses. However, setMoneyRequestAmount() in IOU/index.ts:1440-1442 always calls setMoneyRequestReceiptState(), which merges {receipt: {state: 'OPEN'}} into the transaction draft — even for manual expenses. The useEffect at line 521 of IOURequestStepConfirmation.tsx then picks up this phantom receipt and populates receiptFiles, making the length check truthy.
So for a manual expense with amount=0: amount === 0 is true, receiptFiles.length is truthy (due to the phantom receipt), and gpsRequired evaluates to truthy, incorrectly triggering the LocationPermissionModal at line 1577.
Note: The existing analysis suggested PR #83354 introduced this, but PR #83354 only modified useReceiptScan.ts (the scan flow). Manual expenses never go through useReceiptScan — they go through IOURequestStepAmount → IOURequestStepConfirmation. The bug in the confirmation page's gpsRequired logic is independent of that PR and was likely discovered during its regression testing.
What changes do you think we should make in order to solve the problem?
Add an isScanRequest(transaction) check to the gpsRequired condition in IOURequestStepConfirmation.tsx:285. The isScanRequest function is already imported (line 82) and correctly returns false for manual expenses by checking transaction.iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN:
This is a targeted one-line fix that preserves the GPS behavior for actual scanned receipts while preventing the location modal from appearing for manual expenses.
What alternative solutions did you explore? (Optional)
Fixing setMoneyRequestReceiptState: Preventing it from setting phantom receipt state on manual expenses would also fix this, but that function is called from multiple places (setMoneyRequestAmount, setMoneyRequestCreated, etc.) and may have other consumers that rely on the behavior. The isScanRequest guard on gpsRequired is a safer, more targeted fix.
Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, @MelvinBot <your feedback> to refine this analysis, or explain why you are rejecting Melvin's proposal.
Please re-state the problem that we are trying to solve in this issue.
When creating a manual expense with 0 amount, the "Allow location access" modal incorrectly appears. This should only happen for scanned receipt expenses where GPS is needed to determine currency from location.
What is the root cause of that problem?
The gpsRequired condition in IOURequestStepConfirmation.tsx (line 285) uses transaction?.amount === 0 as a proxy for "this is a scanned receipt." But manual expenses can also have 0 amount, and the condition doesn't verify the request type:
This means any 0-amount expense that happens to have receipt files will trigger the location permission flow, even if it's not a scan request.
What changes do you think we should make in order to solve the problem?
Add isScanRequest(transaction) to the gpsRequired condition in IOURequestStepConfirmation.tsx. This function checks transaction.iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN, ensuring the location modal only appears for actual scan requests. It's already imported in the file.
What alternative solutions did you explore? (Optional)
Reverting PR #83354 was considered, but that would re-introduce the original issue (#81184) where scanned receipts weren't collecting GPS for currency detection. The targeted fix preserves that behavior while preventing the regression for manual expenses.
Activity
melvin-bot commentedon Mar 13, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #83354
melvin-bot commentedon Mar 13, 2026
💬 A slack conversation has been started in #expensify-open-source
OSBotify commentedon Mar 13, 2026
Investigation Summary
Classification: Frontend bug
Causing PR: #83354 - "Pass locationPermissionGranted=true when permission was already grant..." by @MobileMage (High confidence)
Related Issues: #81184 (original issue that PR 83354 was fixing)
Recommendation: REVERT
PR #83354 should be reverted. While it successfully fixed the original issue (scanned receipts not collecting GPS for currency detection), it introduced a regression where manual expenses with 0 amount now incorrectly trigger the location permission modal.
Labels: Keeping
DeployBlockerCash- this is an App bug that requires reverting an App PR. RemovingDeployBlockeras this is not a backend issue.Detailed Analysis
Evidence
PR #83354 modified
src/pages/iou/request/step/IOURequestStepScan/useReceiptScan.tsto passlocationPermissionGranted=truewhen:shouldSkipConfirmationis truegpsRequiredis true (amount === 0)The problem is in the
gpsRequiredcondition:This condition checks for 0 amount expenses but does NOT distinguish between:
Verification
From the issue reproduction steps:
The fix applies to lines 234-246 in
processReceipts()and lines 254-263 insubmitReceipts()in useReceiptScan.ts, where the GPS requirement logic does not check the expense type.Root Cause
The PR correctly identified that scanned receipts with 0 amount need GPS coordinates for currency detection when permission is already granted. However, the implementation applies this logic to ALL expenses with 0 amount, including manual expenses that should never trigger location permission flows.
The same issue exists in
IOURequestStepConfirmation.tsxline 285:This condition should additionally check if the expense is a scanned receipt (e.g., using
isScanRequest(transaction)) before requiring GPS.github-actions commentedon Mar 13, 2026
👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:
MobileMage commentedon Mar 13, 2026
Looking into this
MelvinBot commentedon Mar 13, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When creating a manual expense with 0 amount (+ > Create expense > Manual > Enter 0 > Next > Confirm), the "Allow location access" modal incorrectly appears. This modal should only appear for scanned receipts that need GPS coordinates to determine currency from location — never for manual expenses.
What is the root cause of that problem?
The
gpsRequiredcondition inIOURequestStepConfirmation.tsx:285usestransaction.amount === 0as a proxy for "this is a scanned receipt needing GPS," but manual expenses can also have amount=0:The condition relies on
Object.values(receiptFiles).lengthbeing truthy to filter out non-receipt expenses. However,setMoneyRequestAmount()inIOU/index.ts:1440-1442always callssetMoneyRequestReceiptState(), which merges{receipt: {state: 'OPEN'}}into the transaction draft — even for manual expenses. TheuseEffectat line 521 ofIOURequestStepConfirmation.tsxthen picks up this phantom receipt and populatesreceiptFiles, making the length check truthy.So for a manual expense with amount=0:
amount === 0is true,receiptFiles.lengthis truthy (due to the phantom receipt), andgpsRequiredevaluates to truthy, incorrectly triggering theLocationPermissionModalat line 1577.Note: The existing analysis suggested PR #83354 introduced this, but PR #83354 only modified
useReceiptScan.ts(the scan flow). Manual expenses never go throughuseReceiptScan— they go throughIOURequestStepAmount→IOURequestStepConfirmation. The bug in the confirmation page'sgpsRequiredlogic is independent of that PR and was likely discovered during its regression testing.What changes do you think we should make in order to solve the problem?
Add an
isScanRequest(transaction)check to thegpsRequiredcondition inIOURequestStepConfirmation.tsx:285. TheisScanRequestfunction is already imported (line 82) and correctly returnsfalsefor manual expenses by checkingtransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN:This is a targeted one-line fix that preserves the GPS behavior for actual scanned receipts while preventing the location modal from appearing for manual expenses.
What alternative solutions did you explore? (Optional)
Reverting PR Pass locationPermissionGranted=true when permission was already grant… #83354: As suggested by the existing analysis. However, since PR Pass locationPermissionGranted=true when permission was already grant… #83354 didn't introduce this specific bug (it only changed the scan flow in
useReceiptScan.ts), a revert would undo the legitimate fix from [$250] Expense- Receipt scan without currency assigns incorrect currency based on location #81184 without actually fixing this issue.Fixing
setMoneyRequestReceiptState: Preventing it from setting phantom receipt state on manual expenses would also fix this, but that function is called from multiple places (setMoneyRequestAmount,setMoneyRequestCreated, etc.) and may have other consumers that rely on the behavior. TheisScanRequestguard ongpsRequiredis a safer, more targeted fix.Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR,@MelvinBot <your feedback>to refine this analysis, or explain why you are rejecting Melvin's proposal.MobileMage commentedon Mar 13, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When creating a manual expense with 0 amount, the "Allow location access" modal incorrectly appears. This should only happen for scanned receipt expenses where GPS is needed to determine currency from location.
What is the root cause of that problem?
The
gpsRequiredcondition inIOURequestStepConfirmation.tsx(line 285) usestransaction?.amount === 0as a proxy for "this is a scanned receipt." But manual expenses can also have 0 amount, and the condition doesn't verify the request type:This means any 0-amount expense that happens to have receipt files will trigger the location permission flow, even if it's not a scan request.
What changes do you think we should make in order to solve the problem?
Add
isScanRequest(transaction)to thegpsRequiredcondition inIOURequestStepConfirmation.tsx. This function checkstransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN, ensuring the location modal only appears for actual scan requests. It's already imported in the file.What alternative solutions did you explore? (Optional)
Reverting PR #83354 was considered, but that would re-introduce the original issue (#81184) where scanned receipts weren't collecting GPS for currency detection. The targeted fix preserves that behavior while preventing the regression for manual expenses.
Valforte commentedon Mar 13, 2026
@MobileMage for timeliness, I'll revert the original PR, can you recreate your PR with the proposed fix?
MobileMage commentedon Mar 13, 2026
Yup @Valforte
Valforte commentedon Mar 13, 2026
I actually changed my mind and applied your suggested fix, PR is #85261
MobileMage commentedon Mar 13, 2026
Oh okay, great!
IuliiaHerets commentedon Mar 13, 2026
Chrome / v9.3.37-7
Not reproduce
Screen.Recording.2026-03-13.at.21.19.18.mp4
luacmartins commentedon Mar 13, 2026
Fixed. Closing.