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
[$250] mWeb – Compose box closes after sending messages #83731
👋 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.
Classification: Frontend bug (requires investigation) Causing PR: Unable to determine with high confidence Related Issues: None identified
Recommendation: NEEDS INVESTIGATION
The root cause cannot be determined with confidence from the available evidence. The compose box closing after sending messages on mWeb Android Chrome is likely an indirect side-effect from another change in the staging deploy.
Reasoning:
No direct changes to ReportActionCompose, ComposerWithSuggestions, or SendButton components were found in the staging deploy
No modifications to willBlurTextInputOnTapOutside, KeyboardUtils, or ComposerFocusManager libraries
The bug is staging-only (not reproducible in production), confirming it was introduced in v9.3.27-0
The behavior suggests something is causing the compose input to blur/lose focus after message submission, but the blur logic itself appears unchanged
Investigation performed:
Reviewed all 100 PRs in the v9.3.27-0 staging deploy checklist
Searched for PRs affecting composer, keyboard, blur, focus, and mWeb-specific behavior
Checked recent commits to composer-related files and focus/blur utilities
No PRs in the staging deploy directly modify the compose box or message sending flow
Next steps:
Tag the original issue reporter @jponikarchuk for additional context
Test if the issue reproduces when reverting recent PRs one by one
Check if there are any timing-related changes (debounce, setTimeout) that might affect the blur behavior
Investigate if changes to navigation, screen transitions, or keyboard handling could indirectly affect the composer
Labels: No label changes at this time - keeping DeployBlockerCash until root cause is identified
cc @jponikarchuk@sonialiap@blimpich - Unable to identify a specific causing PR. This requires deeper investigation, potentially reverting recent PRs to bisect the issue.
Summary: After sending a message on mWeb (Android Chrome), the compose box closes. This is a regression in staging v9.3.27-0, not present in production.
Root Cause: Two changes in this release combine to cause the bug:
PR #81280 ("Report Actions Derived Value") introduces an async Onyx-derived value VISIBLE_REPORT_ACTIONS that ReportActionsView subscribes to. When a message is sent, the optimistic REPORT_ACTIONS update triggers an async recomputation of this derived value, which causes ReportActionsView to re-render a second time when the derived value settles. On mWeb Android Chrome, this additional re-render (combined with the resetHeight() and async scheduleOnUI-based input clear) causes a layout shift that triggers the browser to dismiss the virtual keyboard, making the compose box appear to "close."
PR #76104 changes chatContentScrollViewPlatformStyles from overflow: 'hidden' to overflow: 'clip' on web (src/styles/utils/chatContentScrollViewPlatformStyles/index.ts). This changes how the chat content area handles overflow — overflow: clip does not create a formatting context the way overflow: hidden does, which affects how Android Chrome handles viewport/keyboard interactions during layout shifts.
ReportActionsView.tsx:241 — visibleReportActions useMemo depends on visibleReportActionsData, so any derived value update triggers recomputation
ReportActionsView.tsx:333-335 — a hasDerivedValueTimingIssue guard renders a non-animated skeleton if reportActions.length > 0 but visibleReportActions.length === 0. If this guard triggers even briefly on mWeb, it unmounts the ReportActionsList from the DOM entirely
PR fix: Allow multiple loads in useLoadReportActions hook #76104 also removes the didLoadNewerChats one-shot guard in useLoadReportActions, allowing loadNewerChats to fire multiple times, potentially triggering more Onyx updates and re-renders after sending
Recommended Fix:
Quickest test: Revert the overflow: 'hidden' → overflow: 'clip' change in src/styles/utils/chatContentScrollViewPlatformStyles/index.ts and check if the issue resolves on mWeb
If needed: Optimize the visibleReportActions useMemo in ReportActionsView.tsx to only depend on the specific report's data from the derived value (not the entire object), reducing unnecessary re-renders
If the skeleton flashes: The hasDerivedValueTimingIssue guard at ReportActionsView.tsx:333 could use the previous visibleReportActions value as a fallback instead of showing a skeleton, preventing DOM unmount/remount on mWeb
Open Questions
Runtime confirmation is needed: does the hasDerivedValueTimingIssue skeleton guard actually trigger after sending a message on mWeb, or is the issue purely from re-render layout shifts?
Is this also reproducible on iOS mWeb Safari? The bug report only checks Android mWeb Chrome.
Detailed Investigation
Evidence Chain
Message send flow on mWeb:
User taps Send → handleSendMessage in ReportActionCompose.tsx
composerRef.current?.resetHeight() shrinks composer to empty height
scheduleOnUI(clearWorklet) queues the input clear for next animation frame (async via requestAnimationFrame on web per react-native-worklets/src/threads.ts:92)
Optimistic REPORT_ACTIONS update fires → reportActions from usePaginatedReportActions includes new action
visibleReportActions useMemo recomputes → new action visible (has pendingAction → bypasses derived value per ReportActionsUtils.ts:1209)
ASYNC:VISIBLE_REPORT_ACTIONS derived value recomputes (triggered by REPORT_ACTIONS change)
When derived value settles → visibleReportActionsData changes → visibleReportActions useMemo recomputes AGAIN
This second re-render, combined with the height reset from step 2 and the async clear from step 3, causes layout thrashing
On Android Chrome mWeb, the browser dismisses the virtual keyboard due to the layout shifts
Without the keyboard, the compose box appears "closed"
Why mWeb Android Chrome specifically:
Android Chrome is aggressive about dismissing the virtual keyboard when DOM layout changes significantly
Activity
melvin-bot commentedon Feb 27, 2026
Triggered auto assignment to @sonialiap (
Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.github-actions commentedon Feb 27, 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:
melvin-bot commentedon Feb 27, 2026
Triggered auto assignment to @blimpich (
DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.melvin-bot commentedon Feb 27, 2026
💬 A slack conversation has been started in #expensify-open-source
OSBotify commentedon Feb 27, 2026
Investigation Summary
Classification: Frontend bug (requires investigation)
Causing PR: Unable to determine with high confidence
Related Issues: None identified
Recommendation: NEEDS INVESTIGATION
The root cause cannot be determined with confidence from the available evidence. The compose box closing after sending messages on mWeb Android Chrome is likely an indirect side-effect from another change in the staging deploy.
Reasoning:
ReportActionCompose,ComposerWithSuggestions, orSendButtoncomponents were found in the staging deploywillBlurTextInputOnTapOutside,KeyboardUtils, orComposerFocusManagerlibrariesInvestigation performed:
Next steps:
Labels: No label changes at this time - keeping
DeployBlockerCashuntil root cause is identifiedcc @jponikarchuk @sonialiap @blimpich - Unable to identify a specific causing PR. This requires deeper investigation, potentially reverting recent PRs to bisect the issue.
MelvinBot commentedon Feb 27, 2026
🔍 Issue Analysis
Summary: After sending a message on mWeb (Android Chrome), the compose box closes. This is a regression in staging v9.3.27-0, not present in production.
Root Cause: Two changes in this release combine to cause the bug:
PR #81280 ("Report Actions Derived Value") introduces an async Onyx-derived value
VISIBLE_REPORT_ACTIONSthatReportActionsViewsubscribes to. When a message is sent, the optimisticREPORT_ACTIONSupdate triggers an async recomputation of this derived value, which causesReportActionsViewto re-render a second time when the derived value settles. On mWeb Android Chrome, this additional re-render (combined with theresetHeight()and asyncscheduleOnUI-based input clear) causes a layout shift that triggers the browser to dismiss the virtual keyboard, making the compose box appear to "close."PR #76104 changes
chatContentScrollViewPlatformStylesfromoverflow: 'hidden'tooverflow: 'clip'on web (src/styles/utils/chatContentScrollViewPlatformStyles/index.ts). This changes how the chat content area handles overflow —overflow: clipdoes not create a formatting context the wayoverflow: hiddendoes, which affects how Android Chrome handles viewport/keyboard interactions during layout shifts.Key evidence:
ReportActionsView.tsx:105subscribes toONYXKEYS.DERIVED.VISIBLE_REPORT_ACTIONS(new in PR Report Actions Derived Value #81280)ReportActionsView.tsx:241—visibleReportActionsuseMemo depends onvisibleReportActionsData, so any derived value update triggers recomputationReportActionsView.tsx:333-335— ahasDerivedValueTimingIssueguard renders a non-animated skeleton ifreportActions.length > 0butvisibleReportActions.length === 0. If this guard triggers even briefly on mWeb, it unmounts theReportActionsListfrom the DOM entirelysrc/styles/utils/chatContentScrollViewPlatformStyles/index.ts— changed fromoverflow: 'hidden'tooverflow: 'clip'(PR fix: Allow multiple loads inuseLoadReportActionshook #76104), applied atReportActionsList.tsx:834useLoadReportActionshook #76104 also removes thedidLoadNewerChatsone-shot guard inuseLoadReportActions, allowingloadNewerChatsto fire multiple times, potentially triggering more Onyx updates and re-renders after sendingRecommended Fix:
overflow: 'hidden'→overflow: 'clip'change insrc/styles/utils/chatContentScrollViewPlatformStyles/index.tsand check if the issue resolves on mWebvisibleReportActionsuseMemo inReportActionsView.tsxto only depend on the specific report's data from the derived value (not the entire object), reducing unnecessary re-rendershasDerivedValueTimingIssueguard atReportActionsView.tsx:333could use the previousvisibleReportActionsvalue as a fallback instead of showing a skeleton, preventing DOM unmount/remount on mWebOpen Questions
hasDerivedValueTimingIssueskeleton guard actually trigger after sending a message on mWeb, or is the issue purely from re-render layout shifts?Detailed Investigation
Evidence Chain
Message send flow on mWeb:
handleSendMessageinReportActionCompose.tsxcomposerRef.current?.resetHeight()shrinks composer to empty heightscheduleOnUI(clearWorklet)queues the input clear for next animation frame (async viarequestAnimationFrameon web perreact-native-worklets/src/threads.ts:92)REPORT_ACTIONSupdate fires →reportActionsfromusePaginatedReportActionsincludes new actionvisibleReportActionsuseMemo recomputes → new action visible (haspendingAction→ bypasses derived value perReportActionsUtils.ts:1209)VISIBLE_REPORT_ACTIONSderived value recomputes (triggered byREPORT_ACTIONSchange)visibleReportActionsDatachanges →visibleReportActionsuseMemo recomputes AGAINWhy mWeb Android Chrome specifically:
overflow: 'clip'change (PR fix: Allow multiple loads inuseLoadReportActionshook #76104) removed the scroll formatting context from the chat content area, making the layout less stable during re-rendersRelevant Code
src/pages/inbox/report/ReportActionsView.tsx:105— subscribes to derived valuesrc/pages/inbox/report/ReportActionsView.tsx:220-242—visibleReportActionsuseMemo withvisibleReportActionsDatadependencysrc/pages/inbox/report/ReportActionsView.tsx:333-335— skeleton guard for derived value timing issuesrc/libs/ReportActionsUtils.ts:1196-1232—isReportActionVisiblewith derived value fallbackssrc/libs/actions/OnyxDerived/configs/visibleReportActions.ts— new derived value config (PR Report Actions Derived Value #81280)src/styles/utils/chatContentScrollViewPlatformStyles/index.ts—overflow: 'clip'change (PR fix: Allow multiple loads inuseLoadReportActionshook #76104)src/hooks/useLoadReportActions.ts— removed one-shot guard (PR fix: Allow multiple loads inuseLoadReportActionshook #76104)PRs Involved
Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR, or@MelvinBot <your feedback>to refine this analysis.6 remaining items
parasharrajat commentedon Feb 27, 2026
@chrispader @ishpaul777 regression from your PR.
fix: scroll to bottom instead of navigating on mWeb message send
blimpich commentedon Feb 27, 2026
Conversation here: https://expensify.slack.com/archives/C01GTK53T8Q/p1772228908512959?thread_ts=1772210671.848989&cid=C01GTK53T8Q
blimpich commentedon Feb 27, 2026
Confirmed revert fixes it here: https://expensify.slack.com/archives/C01GTK53T8Q/p1772228908512959?thread_ts=1772210671.848989&cid=C01GTK53T8Q
melvin-bot commentedon Feb 27, 2026
If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.
If a regression has occurred and you are the assigned CM follow the instructions here.
If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.
blimpich commentedon Feb 28, 2026
deployed fix to staging, requested retest here: https://expensify.slack.com/archives/C09V78U42D8/p1772237489391169
m-natarajan commentedon Feb 28, 2026
Issue is not reproducible on Samsung S23FE/ Chrome in v9.3.27-2
83731.mp4