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
App crashes when swipe back from description and tap on it #98993
Version Number: 9.4.56-0 Reproducible in staging?: Yes Reproducible in production?: Yes If this was caught during regression testing, add the test name, ID and link from BrowserStack:#98808 Email or phone of affected tester (no customers):emady.syed1234+daddu@gmail.com Issue reported by: Applause Internal Team Bug source: Pull Request QA execution Device used: iPhone 12 / iOS 26.3.1 App Component: Money Requests
Action Performed:
Open App
Create an expense
Enter text in description field
Swipe back and quickly tap on any field before discard pop up appears
This is a native iOS crash in the discard-changes → re-focus path of the expense description step. It is not reproducible on web/Android by design, so it could not be verified in this run's web session — the fix needs iOS device testing.
The flow:
On the description step you type text, then iOS edge-swipe back. Because there are unsaved changes, useDiscardChangesConfirmation intercepts the removal via usePreventRemove and shows the discard modal. Showing the modal flips the field to editable={false}, which on iOS resigns the keyboard while RN's JS-side isFocused() still reports true.
Because the field still reports focused, this schedules a deferred native call — requestIdleCallback(() => KeyboardController.setFocusTo('current')) (native reloadInputViews + focus on iOS). Because the user tapped mid-transition, by the time the idle callback runs the screen is unmounting / the first responder is stale, so setFocusTo('current') runs against a detached native input and crashes.
Note on PR #98808 (whose QA surfaced this): its only production change is Android-only (gating forceKeyboardIfAlreadyFocused off on Android). The iOS path is byte-identical before/after #98808, so #98808 did not introduce the crash — it just exercised the exact flow. The crashing iOS KeyboardController.setFocusTo('current') mechanism was introduced earlier by PR #97823 (the fix for Expensify/App#97604).
Inside the requestIdleCallback, re-check textInput?.isFocused?.() (and/or that the ref is still mounted) immediately before calling KeyboardController.setFocusTo('current'), and skip the call otherwise; wrap in a try/catch as a native-safety net.
Alternatively, in the description step's onCancel, only re-focus when the screen useIsFocused() is still true.
Investigation details & confidence
The attached crash2.txt is a full device syslog with no symbolicated app stack trace, so root cause was established from code, not the log.
Confidence is Medium, not High, because there is no production/Sentry confirmation of the exact crashing frame — Sentry was not reachable in this run. To confirm, check Sentry (iOS, v9.4.56) for crash frames referencing react-native-keyboard-controller / KeyboardController.setFocusTo / reloadInputViews correlated with the IOU description discard flow.
Next Steps for Contributor+ team: To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/98993) to create a draft PR. To refine:@MelvinBot <your feedback> To reject: Explain why you are rejecting Melvin's proposal.
The Create expense page layout changed and no more > to navigate to description and go back. we can now directly enter the description.
Blocked from retesting this one.
Activity
MelvinBot commentedon Aug 19, 2026
Proposal
Root cause (Medium confidence)
This is a native iOS crash in the discard-changes → re-focus path of the expense description step. It is not reproducible on web/Android by design, so it could not be verified in this run's web session — the fix needs iOS device testing.
The flow:
useDiscardChangesConfirmationintercepts the removal viausePreventRemoveand shows the discard modal. Showing the modal flips the field toeditable={false}, which on iOS resigns the keyboard while RN's JS-sideisFocused()still reportstrue.onCancelfires and callsfocusComposerWithDelay(inputRef.current)(true, undefined, shouldForceKeyboardIfAlreadyFocused()). On iOSshouldForceKeyboardIfAlreadyFocused()returnstrue.requestIdleCallback(() => KeyboardController.setFocusTo('current'))(nativereloadInputViews+ focus on iOS). Because the user tapped mid-transition, by the time the idle callback runs the screen is unmounting / the first responder is stale, sosetFocusTo('current')runs against a detached native input and crashes.Note on PR #98808 (whose QA surfaced this): its only production change is Android-only (gating
forceKeyboardIfAlreadyFocusedoff on Android). The iOS path is byte-identical before/after #98808, so #98808 did not introduce the crash — it just exercised the exact flow. The crashing iOSKeyboardController.setFocusTo('current')mechanism was introduced earlier by PR #97823 (the fix forExpensify/App#97604).Recommended fix
Guard the deferred native focus so it no-ops when the input is no longer valid/focused or the screen is unmounting, in
requestKeyboardForFocusedComposer/index.native.ts:requestIdleCallback, re-checktextInput?.isFocused?.()(and/or that the ref is still mounted) immediately before callingKeyboardController.setFocusTo('current'), and skip the call otherwise; wrap in atry/catchas a native-safety net.onCancel, only re-focus when the screenuseIsFocused()is still true.Investigation details & confidence
crash2.txtis a full device syslog with no symbolicated app stack trace, so root cause was established from code, not the log.react-native-keyboard-controller/KeyboardController.setFocusTo/reloadInputViewscorrelated with the IOU description discard flow.Expensify/App#97604("iOS - No focus on description field when cancel changes") — the fix for it (Fix: return focus and soft keyboard to description input on iOS after canceling discard modal #97823, carried forward by Fix: gate forceKeyboardIfAlreadyFocused per-platform to remove Android discard-changes keyboard regression #98808) introduced this force-refocus path.Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/98993)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
view run
melvin-bot commentedon Aug 19, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @rojiphil (
External)melvin-bot commentedon Aug 19, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022090136199108665557
melvin-bot commentedon Aug 24, 2026
@rojiphil Eep! 4 days overdue now. Issues have feelings too...
melvin-bot commentedon Aug 26, 2026
@rojiphil 6 days overdue. This is scarier than being forced to listen to Vogon poetry!
rojiphil commentedon Aug 28, 2026
I am unable to reproduce this issue
98993-ios-hybrid-001.mp4
getusha commentedon Aug 28, 2026
I was able to reproduce, taking over!
mkhutornyi commentedon Aug 28, 2026
Looks like this is regression from #97823.
This was reported within 7-day regression window.
cc: @ikevin127
25 remaining items
melvin-bot commentedon Sep 10, 2026
@getusha Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!
getusha commentedon Sep 11, 2026
Reviewing
getusha commentedon Sep 14, 2026
Trying to reproduce on simulator.
melvin-bot commentedon Sep 16, 2026
@getusha this issue is now 4 weeks old, please consider:
Thanks!
melvin-bot commentedon Sep 17, 2026
@getusha Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!
melvin-bot commentedon Sep 21, 2026
@getusha Still overdue 6 days?! Let's take care of this!
melvin-bot commentedon Sep 23, 2026
@getusha Now this issue is 8 days overdue. Are you sure this should be a Daily? Feel free to change it!
getusha commentedon Sep 25, 2026
The page changed we can close it.
m-natarajan commentedon Sep 25, 2026
The Create expense page layout changed and no more > to navigate to description and go back. we can now directly enter the description.
Blocked from retesting this one.
ScreenRecording_09-25-2026.20-06-17_1.MP4