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
Onboarding modal briefly shows blank page when reselecting Join my company workspace #104001
Version Number: 9.5.9-0 Reproducible in staging?: Yes Reproducible in production?: N/A - new feature, doesn't exist in prod If this was caught during regression testing, add the test name, ID and link from BrowserStack:#103652 Email or phone of affected tester (no customers):[email protected] Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: Mac 26.5 / Chroem App Component: Other
Action Performed:
1 .Go to staging.new.expensify.com
2. Log in with a new Gmail account.
3. On work email step, click Skip.
4. Select Join my company workspace.
5. Enter any Expensifail account > Add work email.
6. Click app back button.
7. Select Join my company workspace.
Expected Result:
Onboarding modal will not show blank page when reselecting Join my company workspace after work email step fails.
Actual Result:
Onboarding modal briefly shows blank page when reselecting Join my company workspace after work email step fails.
👋 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.
Root cause: The Back button on the blocked work email screen doesn't clear isMergingAccountBlocked. When you reselect "Join my company workspace", the clear runs in the background while navigation starts right away. As a result, the screens mount against stale merge-blocked state and briefly render empty.
Recommendation: Fix forward instead of reverting. The bug is a brief flash on an edge-case path of a new feature. This feature has already been reverted and re-landed once, and it depends on backend changes.
Suggested fix:
In BaseOnboardingWorkEmail.tsx:365, have onBackButtonPress call clearOnboardingMergeAccountBlocked() before goBack when isMergingAccountBlocked is set. This matches what "Got it" does.
In BaseOnboardingPurpose.tsx:134-144, navigate only after the clear finishes. For example, have clearOnboardingMergeAccountBlocked return a Promise.all of its Onyx writes, then navigate in .then().
Investigation details
Step 5: An Expensifail address is domain-controlled. AddWorkEmail sets isMergingAccountBlocked: true and the domainControlledSubtitle error key (Session/index.ts:1786-1793).
Step 7: Purpose calls clearOnboardingMergeAccountBlocked() without waiting, then navigates right away (BaseOnboardingPurpose.tsx:134-144). The clear uses Onyx.merge and Onyx.set(null), so it lands after the push (Welcome/index.ts:229-233).
Not confirmed: I didn't reproduce this in the app, so I can't say which screen draws the fully blank frame, header included. The most likely candidate is Purpose returning null mid-transition. Either way, both fixes above remove the stale state that causes it.
Next Steps: Reply with @MelvinBot implement this to create a draft PR, or @MelvinBot <your feedback> to refine this analysis.
Summary: The causing PR and the fix from my earlier comment still stand: clear the merge-blocked state when you press Back. One part of that comment was wrong, though. Purpose can't return null during this flow, so it isn't the blank frame. I still haven't found which component draws the fully empty card.
Correction: I suggested that BaseOnboardingPurpose.tsx:223-225 returns null mid-transition. It can't. The error message is cleared with Onyx.set(null), and that never puts useOnyx into a loading state. I also found no other path in the work email screen or the onboarding navigator that renders nothing.
What the code does show: Back at BaseOnboardingWorkEmail.tsx:365 leaves isMergingAccountBlocked set. Purpose clears the flag without waiting, then pushes a new work email screen (BaseOnboardingPurpose.tsx:134-144). That new screen can mount for a frame in the blocked state before switching to the form. This stale state is the only glitch the code explains.
Web repro: On a local dev build, steps 1–6 behave as described. I couldn't capture the blank frame in 6 tries because screenshots are too slow to catch it. The app always settled on the work email form. The rejected expensifail.com address was still filled in.
Screenshots
Recommended fix: Make the Back handler at BaseOnboardingWorkEmail.tsx:365 do what "Got it" does at L274-278. That means setOnboardingErrorMessage(null) and setOnboardingMergingAccountBlocked(false) before goBack. Reselecting the option then never sees stale state, and the clear in Purpose becomes a safety net. Then retest the steps on staging to confirm the flash is gone.
To pin down the blank frame: Record the flow, or log which onboarding screen mounts at each step. Check whether the empty card shows only during the slide-in animation.
Next Steps: Reply with @MelvinBot implement this to create a draft PR, or @MelvinBot <your feedback> to refine this analysis.
Yes, it looks fixed on main with Clear the onboarding work email error when pressing Back to the intent list: after the domain-controlled block and Back, reselecting "Join my company workspace" went straight to the work email form, with no blank frame in rapid screenshots. Two caveats: the PR isn't on staging yet (it deploys after the next production release), and screenshots couldn't catch the brief flash before the fix either, so please retest on staging to confirm.
Step
Status
Sign in with a new account opens the onboarding modalThe onboarding modal opened directly to the work email step.
✅
On the work email step, Skip shows the intent list"What do you want to do today?" showed with all six options, including "Join my company workspace".
✅
Selecting "Join my company workspace" shows the work email form"What's your work email?" showed with a Back button, the Work email field, Skip, and Add work email.
✅
Adding an Expensifail work email shows the full-screen blocked view[email protected] showed "Couldn't add work email" with "[email protected] is a domain controlled login for an existing Expensify account." and a "Got it" button. Four other Expensifail addresses only showed inline form errors (closed account or SSO).
✅
Header Back returns to the intent list with no stale errorThe intent list showed with no error text. "undefined is a domain controlled login" wasn't present.
✅
Reselecting "Join my company workspace" shows no blank modal and lands on the formThree rapid screenshots right after the tap all showed the full work email form, not the blocked view. No empty modal appeared in any capture.
Activity
applause-bot commentedon Oct 14, 2026
While Applause doesn't embed attachments for this bug, here are the links for quick view:
https://platform.applause.com/services/links/v1/external/3b125b5948fefc84c78551ed984c50371f1dce57923b36d79babbff7195b93a7
https://platform.applause.com/services/links/v1/external/6a6f4d074465f7cc1736e3a96cdf59886feebd319fff4bb6e9516394d6a78a21
melvin-bot commentedon Oct 14, 2026
You have been assigned to this deploy blocker because you recently merged this PR: #103652
melvin-bot commentedon Oct 14, 2026
@iwiznia @abzokhattab you have been assigned to this deploy blocker because you reviewed the offending PR: #103652
melvin-bot commentedon Oct 14, 2026
@carlosmiceli you have been assigned to this deploy blocker because you authored the offending PR: #103652
melvin-bot commentedon Oct 14, 2026
💬 A slack conversation has been started in #expensify-open-source
github-actions commentedon Oct 14, 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:
carlosmiceli commentedon Oct 14, 2026
@MelvinBot please investigate
carlosmiceli commentedon Oct 14, 2026
@jponikarchuk Julia, I don't think I see what the blocker is here?
MelvinBot commentedon Oct 14, 2026
Deploy Blocker Analysis
Causing PR: [Payment due @abzokhattab] Add the join-workspace onboarding intent and Concierge follow up tasks (high confidence). The auto-assignment is correct. No other PR on the StagingDeployCash checklist changes the Purpose or work email screens.
Root cause: The Back button on the blocked work email screen doesn't clear
isMergingAccountBlocked. When you reselect "Join my company workspace", the clear runs in the background while navigation starts right away. As a result, the screens mount against stale merge-blocked state and briefly render empty.Recommendation: Fix forward instead of reverting. The bug is a brief flash on an edge-case path of a new feature. This feature has already been reverted and re-landed once, and it depends on backend changes.
Suggested fix:
BaseOnboardingWorkEmail.tsx:365, haveonBackButtonPresscallclearOnboardingMergeAccountBlocked()beforegoBackwhenisMergingAccountBlockedis set. This matches what "Got it" does.BaseOnboardingPurpose.tsx:134-144, navigate only after the clear finishes. For example, haveclearOnboardingMergeAccountBlockedreturn aPromise.allof its Onyx writes, then navigate in.then().Investigation details
AddWorkEmailsetsisMergingAccountBlocked: trueand thedomainControlledSubtitleerror key (Session/index.ts:1786-1793).Navigation.goBack(ROUTES.ONBOARDING_PURPOSE.getRoute())(BaseOnboardingWorkEmail.tsx:365). The "Got it" path,handleRegularJoinWorkspaceErrorConfirm, does reset both values (BaseOnboardingWorkEmail.tsx:274-278).clearOnboardingMergeAccountBlocked()without waiting, then navigates right away (BaseOnboardingPurpose.tsx:134-144). The clear usesOnyx.mergeandOnyx.set(null), so it lands after the push (Welcome/index.ts:229-233).BaseOnboardingWorkEmail.tsx:369), then switches when the clear lands. Purpose returnsnullwhile its error key reads as loading (BaseOnboardingPurpose.tsx:223-225).Not confirmed: I didn't reproduce this in the app, so I can't say which screen draws the fully blank frame, header included. The most likely candidate is Purpose returning
nullmid-transition. Either way, both fixes above remove the stale state that causes it.Next Steps: Reply with
@MelvinBot implement thisto create a draft PR, or@MelvinBot <your feedback>to refine this analysis.MelvinBot commentedon Oct 14, 2026
Follow-up investigation
Summary: The causing PR and the fix from my earlier comment still stand: clear the merge-blocked state when you press Back. One part of that comment was wrong, though. Purpose can't return
nullduring this flow, so it isn't the blank frame. I still haven't found which component draws the fully empty card.Correction: I suggested that
BaseOnboardingPurpose.tsx:223-225returnsnullmid-transition. It can't. The error message is cleared withOnyx.set(null), and that never putsuseOnyxinto a loading state. I also found no other path in the work email screen or the onboarding navigator that renders nothing.What the code does show: Back at
BaseOnboardingWorkEmail.tsx:365leavesisMergingAccountBlockedset. Purpose clears the flag without waiting, then pushes a new work email screen (BaseOnboardingPurpose.tsx:134-144). That new screen can mount for a frame in the blocked state before switching to the form. This stale state is the only glitch the code explains.Web repro: On a local dev build, steps 1–6 behave as described. I couldn't capture the blank frame in 6 tries because screenshots are too slow to catch it. The app always settled on the work email form. The rejected expensifail.com address was still filled in.
Screenshots
Recommended fix: Make the Back handler at
BaseOnboardingWorkEmail.tsx:365do what "Got it" does atL274-278. That meanssetOnboardingErrorMessage(null)andsetOnboardingMergingAccountBlocked(false)beforegoBack. Reselecting the option then never sees stale state, and the clear in Purpose becomes a safety net. Then retest the steps on staging to confirm the flash is gone.To pin down the blank frame: Record the flow, or log which onboarding screen mounts at each step. Check whether the empty card shows only during the slide-in animation.
Next Steps: Reply with
@MelvinBot implement thisto create a draft PR, or@MelvinBot <your feedback>to refine this analysis.carlosmiceli commentedon Oct 14, 2026
Assigning this one to @hungvu193
hungvu193 commentedon Oct 15, 2026
@MelvinBot We already fixed it here right? #104017
Can you verify?
MelvinBot commentedon Oct 15, 2026
🤖 Web test steps verification results: ✅ pass
Yes, it looks fixed on main with Clear the onboarding work email error when pressing Back to the intent list: after the domain-controlled block and Back, reselecting "Join my company workspace" went straight to the work email form, with no blank frame in rapid screenshots. Two caveats: the PR isn't on staging yet (it deploys after the next production release), and screenshots couldn't catch the brief flash before the fix either, so please retest on staging to confirm.

Sign in with a new account opens the onboarding modal
The onboarding modal opened directly to the work email step.On the work email step, Skip shows the intent list
"What do you want to do today?" showed with all six options, including "Join my company workspace".Selecting "Join my company workspace" shows the work email form
"What's your work email?" showed with a Back button, the Work email field, Skip, and Add work email.Adding an Expensifail work email shows the full-screen blocked view
[email protected] showed "Couldn't add work email" with "[email protected] is a domain controlled login for an existing Expensify account." and a "Got it" button. Four other Expensifail addresses only showed inline form errors (closed account or SSO).Header Back returns to the intent list with no stale error
The intent list showed with no error text. "undefined is a domain controlled login" wasn't present.Reselecting "Join my company workspace" shows no blank modal and lands on the form
Three rapid screenshots right after the tap all showed the full work email form, not the blocked view. No empty modal appeared in any capture.hungvu193 commentedon Oct 15, 2026
Closing as duplicate of #104005