Repository navigation
[$175] Copilot-Not here page appears when copilot opens WS chat, switches account and goes to Inbox #102441
Description
Activity
- addedDailyKSv2KSv2BugSomething is broken. Auto assigns a BugZero manager.Something is broken. Auto assigns a BugZero manager.
on Sep 28, 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/ef8f4f96530d5f11206537315f468abb8b5935372ef1953863daddcca27b7f3bProposal
Please re-state the problem that we are trying to solve in this issue.
A copilot opens a workspace chat while acting as another account. After they switch back to their own account and tap Inbox, they see "Hmm... it's not here."
What is the root cause of that problem?
Switching accounts clears Onyx, but it does not reset navigation.
connect()anddisconnect()inDelegate.tscall onlyclearPreservedSearchNavigatorStates(). That function drops only the Search tab's saved state. The Inbox (Reports) split navigator keeps the other account'sREPORTroute.- When the user taps Inbox,
InboxTabButtonfinds that the saved report no longer exists in Onyx. It falls back toNavigation.navigate(ROUTES.INBOX). - On wide layout,
SplitRouterignores a "push sidebar" action and keeps the current central screen. The stale report stays open. - The user has no access to that report, so
ReportNotFoundGuardshows the not-found page.
Code references
- Only Search state is cleared on connect and disconnect: Delegate.ts:226, Delegate.ts:330
- Shared Onyx reset for every delegate transition: Delegate.ts:72-76
- Search-only clear compared with the full clear: usePreserveNavigatorState.ts:32-47
- Logout already does a full clear plus a nav reset: NavigationRoot.tsx:258-266
- Missing-report fallback: InboxTabButton.tsx:177-180
- Wide layout ignores the fallback: SplitRouter.ts:170-177
REPORTkeeps an initialreportIDtaken fromlastAccessedReportIDat mount: ReportsSplitNavigator.tsx:41-65- The navigate-away safety net skips unfocused screens and own workspace chats: ReportNavigateAwayHandler.tsx:199-214
What changes do you think we should make in order to solve the problem?
Handle a delegate switch like a session change for navigation. Do this in one shared place, for example next to
clearOnyxForDelegateTransition(), so it covers connect, disconnect, and the session-restore paths.- Call
clearPreservedNavigatorStates()instead ofclearPreservedSearchNavigatorStates(). - On web, clear the
LAST_VISITED_PATHsessionStorage keys used to restore the Workspaces tab. - Reset the root navigator to a fresh tab navigator with new route keys. You can land on the Settings root or use
Navigation.resetToAppRoot(). New keys remountReportsSplitNavigator, so it drops the stale initialreportIDtoo.
The same fix should also resolve [Exploratory] Copilot - Not Here page appears after switching user back and navigating to workspaces.
What alternative solutions did you explore? (Optional)
Fix the missing-report fallback in
WideInboxTabButtonso it replaces the centralREPORTscreen instead of callingNavigation.navigate(ROUTES.INBOX), which does nothing on wide layout. This fallback bug affects any deleted or missing report, not only copilot switches. It is worth fixing as a second layer, but it would not fix the Workspaces tab.Confidence and open questions
- Web (wide layout): high confidence. I traced every step in code but did not reproduce it live, because the repro needs two linked copilot accounts.
- iOS (narrow layout): not confirmed. On narrow layout, the Inbox fallback pops the stack to the top, so this exact path does not explain the iOS report. The full navigation reset above should still cover it, because it removes all stale tab state.
- Related PR: Submit query lingers on other member when switching accounts via copilot added the Search-only clear. This fix widens it.
- Related open issue: Copilot switch race fires OpenApp with no authToken, landing users on "Hmm... it's not here". It shows the same page but has a different cause: an auth-token race during the switch.
Next Steps for Contributor+ team:
To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/102441)to create a draft PR.
To refine:@MelvinBot <your feedback>
To reject: Explain why you are rejecting Melvin's proposal.
- addedExternalAdded to denote the issue can be worked on by a contributorAdded to denote the issue can be worked on by a contributor
on Sep 28, 2026 Triggered auto assignment to Contributor-plus team member for initial proposal review - @eh2077 (
External)- changed the title
[-]Copilot-Not here page appears when copilot opens WS chat, switches account and goes to Inbox[/-][+][$175] Copilot-Not here page appears when copilot opens WS chat, switches account and goes to Inbox[/+]on Sep 28, 2026 Job added to Upwork: https://www.upwork.com/jobs/~022104643858077127375
Proposal
Please re-state the problem that we are trying to solve in this issue.
When a copilot (User B) acts as another account (User A), opens a workspace chat, switches back to their own account, and navigates to the Inbox tab, a "Hmm... it's not here" (Not Here) page appears instead of the user's Inbox chat list.
What is the root cause of that problem?
When switching delegate accounts (
connect()ordisconnect()insrc/libs/actions/Delegate.ts), Onyx data for the previous account is cleared viaclearOnyxForDelegateTransition(). However, the navigation state is not properly reset:-
Delegate.tsonly invokesNavigation.clearPreservedSearchNavigatorStates()rather than clearing all preserved navigator states:clearPreservedSearchNavigatorStates()only purges preserved route state for the Search tab navigator.- The
ReportsSplitNavigatorretains the previous account's activeREPORTroute (User A's workspace chatreportID) in its preserved state.
-
When the user taps the Inbox tab after switching back to their account:
InboxTabButtondetects that the savedreportIDno longer exists in Onyx for User B and falls back toNavigation.navigate(ROUTES.INBOX).- On wide layouts,
SplitRouterdoes not dismiss or reset the central screen when navigating to the sidebar root (ROUTES.INBOX), keeping the staleREPORTroute active. - Because the report belongs to User A and no longer exists in User B's Onyx store,
ReportNotFoundGuardtriggers and displays the "Hmm... it's not here" screen.
What changes do you think we should make in order to solve the problem?
-
Clear All Preserved Navigator States on Delegate Switch:
Insrc/libs/actions/Delegate.ts:
Replace calls toclearPreservedSearchNavigatorStates()withclearPreservedNavigatorStates()in bothconnect()anddisconnect()so that cached split-navigator states (includingReportsSplitNavigator) are cleared across delegate boundaries:// In Delegate.ts (connect & disconnect) Navigation.clearPreservedNavigatorStates();
-
Reset Navigation to App Root on Delegate Transition:
Similar to the sign-out/session transition inNavigationRoot.tsx, reset navigation state upon completingconnect()anddisconnect():Navigation.resetToAppRoot();
This ensures that the tab bar and split navigators remount with fresh route keys and without stale
lastAccessedReportIDreferences from the previous session. -
Fallback in
SplitRouter/InboxTabButton:
Insrc/components/Navigation/NavigationTabBar/InboxTabButton.tsx, when the target report is not found in Onyx on wide layout, ensure the central screen is cleared or reset toROUTES.HOME/ first available report rather than leaving the inaccessible report mounted.
What alternative solutions did you explore? (Optional)
- Relying solely on
ReportNavigateAwayHandler:ReportNavigateAwayHandlerchecks if the report is missing, but when unfocused or transitioning during account reload, it can fail to redirect before theReportNotFoundGuardmounts. A full navigation reset alongsideclearPreservedNavigatorStates()addresses the root cause deterministically.
Contributor details:
Your Expensify account email: ashusatyarthi@gmail.com
Upwork Profile Link: https://www.upwork.com/freelancers/~010e53044b5828fe60-
- ## Proposal
Please re-state the problem that we are trying to solve in this issue.
When a Copilot (User B) acts as another account (User A), opens a workspace chat, switches back to their own account, and navigates to the Inbox tab, a "Hmm... it's not here" (Not Here / 404) page appears instead of the user's normal Inbox chat list.
What is the root cause of that problem?
In
src/libs/actions/Delegate.ts:
When switching between delegate and primary accounts (connect()anddisconnect()/restoreDelegateSession()):-
Incomplete navigator state cleanup:
Lines 12, 137, and 201 callclearPreservedSearchNavigatorStates():clearPreservedSearchNavigatorStates();
clearPreservedSearchNavigatorStates()was introduced in PR Submit query lingers on other member when switching accounts via copilot #73511 as a narrow fix for the Search tab. It purges keys starting withNAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR.
However, it completely ignores all other split navigators, most notablyReportsSplitNavigator(NAVIGATORS.REPORTS_SPLIT_NAVIGATOR).
As a result,preservedNavigatorStatesinusePreserveNavigatorState.tsretains the entire route state ofReportsSplitNavigator, including User A's active workspace chatreportID. -
Re-attachment of inaccessible report state upon switching back:
- When User B switches back to their own account,
clearOnyxForDelegateTransition()correctly wipes User A's Onyx report data. - When User B navigates to the Inbox tab,
restoreTabNavigatorRoutesreattaches the cachedReportsSplitNavigatorstate frompreservedNavigatorStates. - On wide layouts, the split navigator attempts to mount the central
REPORTscreen with User A's workspace chatreportID. - Because that workspace chat belonged to User A and does not exist in User B's Onyx store,
ReportNotFoundGuard(orReportScreen) triggers and renders the "Hmm... it's not here" error page.
- When User B switches back to their own account,
In contrast, full logout in
src/libs/Navigation/NavigationRoot.tsx(lines 140–145) explicitly callsclearPreservedNavigatorStates():// Drop the previous session's preserved navigator states. Otherwise restoreTabNavigatorRoutes // reattaches the prior TAB_NAVIGATOR subtree to the public sign-in route (which shares that name). clearPreservedNavigatorStates();
Because a delegate account transition switches the authenticated account context just like a session change, failing to clear all preserved navigator states leaves stale route subtrees attached to the new session.
What changes do you think we should make in order to solve the problem?
-
In
src/libs/actions/Delegate.ts:
ReplaceclearPreservedSearchNavigatorStates()withclearPreservedNavigatorStates()in bothconnect()anddisconnect()/restoreDelegateSession():diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts --- a/src/libs/actions/Delegate.ts +++ b/src/libs/actions/Delegate.ts @@ -12,7 +12,7 @@ import type {OnyxCollection, OnyxUpdate} from 'react-native-onyx'; import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; import * as ErrorUtils from '@libs/ErrorUtils'; import Log from '@libs/Log'; -import {clearPreservedSearchNavigatorStates} from '@libs/Navigation/AppNavigator/createSplitNavigator/usePreserveNavigatorState'; +import {clearPreservedNavigatorStates} from '@libs/Navigation/AppNavigator/createSplitNavigator/usePreserveNavigatorState'; import * as NetworkStore from '@libs/Network/NetworkStore'; import * as SequentialQueue from '@libs/Network/SequentialQueue'; import Pusher from '@libs/Pusher'; @@ -137,7 +137,7 @@ function connect( Onyx.update(failureData); return; } - clearPreservedSearchNavigatorStates(); + clearPreservedNavigatorStates(); const restrictedToken = response.restrictedToken; const policyID = activePolicyID; @@ -201,7 +201,7 @@ function disconnect() { return restoreToStashed().then(() => false); } - clearPreservedSearchNavigatorStates(); + clearPreservedNavigatorStates(); const requesterEmail = response.requesterEmail; const authToken = response.authToken;
-
Reset Navigation root state on delegate transition:
Insrc/libs/actions/Delegate.ts, callNavigation.resetToAppRoot()(orNavigation.reset(getStateToResetAfterLogout(navigationRef.getRootState()))) afterclearOnyxForDelegateTransition(). This forces all tab split navigators to remount with clean initial routes, dropping stalelastAccessedReportIDreferences from the previous user. -
In
src/libs/Navigation/AppNavigator/createSplitNavigator/usePreserveNavigatorState.ts:
Deprecate/remove the now redundantclearPreservedSearchNavigatorStatesexport in favor of canonicalclearPreservedNavigatorStates. -
Automated Unit Tests:
Intests/unit/actions/DelegateTest.ts:- Mock
usePreserveNavigatorState'spreservedNavigatorStateswith mock states forREPORTS_SPLIT_NAVIGATORandSEARCH_FULLSCREEN_NAVIGATOR. - Call
connect()/disconnect()and verifyclearPreservedNavigatorStates()is called, assertingpreservedNavigatorStatesis completely cleared across all navigator keys. - Verify that switching back to the primary account does not attempt to restore the copilot's private workspace chat route.
- Mock
What alternative solutions did you explore? (Optional)
- Selectively clearing only
REPORTS_SPLIT_NAVIGATORandSEARCH_FULLSCREEN_NAVIGATOR:
Rejected because workspaces, settings, and other split navigators can also contain private policy or account routes accessible only to Account A (e.g. Issue [Exploratory] Copilot - Not Here page appears after switching user back and navigating to workspaces #98721 Copilot - Not Here page appears after switching user back and navigating to workspaces). Dropping all preserved states on delegate account switch guarantees security and UI consistency across all tabs.
Contributor details
Your Expensify account email: bonnhatnguyen0@gmail.com
Upwork Profile Link: https://www.upwork.com/freelancers/~0139ed4098bdc50182
-
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
@eh2077 Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!
Contributor details
Your Expensify account email: ashusatyarthi@gmail.com
Upwork Profile Link: https://www.upwork.com/freelancers/~010e53044b5828fe60✅ Contributor details stored successfully. Thank you for contributing to Expensify!
@eh2077 Still overdue 6 days?! Let's take care of this!
@eh2077 8 days overdue is a lot. Should this be a Weekly issue? If so, feel free to change it!
not reproducible, @MelvinBot please help check again
Reacted by melvin-boteh2077I re-checked the code on currentmainand nothing fixes this yet. I think it reproduces only on a wide layout, and only when the chat you open is User A's own workspace chat. Either condition missed would explain why you couldn't reproduce it.I couldn't run a live repro. That needs two linked copilot accounts and a magic code, which I can't get in CI.
To reproduce:
- Use a wide layout (desktop web or desktop). On a narrow layout, tapping Inbox returns to the chat list.
- As User B acting as User A, open User A's workspace chat (named after the workspace). Don't use
#admins. For#admins, the app most likely redirects you to Concierge. - Make sure User B is not a member of User A's workspace. Otherwise the chat loads normally.
- Leave that chat open, switch back from the Account tab, then tap Inbox. Don't refresh or open another chat first.
- Expect a brief loading screen, then "Hmm... it's not here."
Why it still happens on current main
- Switching accounts still clears only the Search tab's saved state, so the Inbox tab keeps User A's chat open: Delegate.ts:227, Delegate.ts:331
- Tapping Inbox falls back to
ROUTES.INBOX(InboxTabButton.tsx:177-178). On a wide layout the router keeps the open chat, so the stale chat stays on screen: SplitRouter.ts:170-176 - The safety net that moves the user away from a removed chat skips the user's own workspace chats on purpose. User A's workspace chat counts as one, so the user isn't moved away: ReportNavigateAwayHandler.tsx:169, ReportNavigateAwayHandler.tsx:219.
#adminsisn't skipped, which is why it most likely ends on Concierge instead. - User B can't open that chat, so the request to reload it fails and the not-found page shows: ReportNotFoundGuard.tsx:78
- I checked recent merges for a fix and found none. Fix not-found page after clearing cache, fix: Not here page appears briefly when copiloting into agent's account, and [Performance] Wide pre-mount 1/5: helpers and hidden screen guards don't change this flow.
If it still doesn't reproduce with these steps, please share your platform, window width, and which chat you opened. I'll take another look.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
If you haven’t already, check out our contributing guidelines for onboarding. To join our Slack channel, fill out this form.
Version Number: 9.4.94-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: #102124
Email or phone of affected tester (no customers): N/A
Issue reported by: Applause Internal Team
Bug source: Exploratory - Significant User Experience Deterioration
Device used: MacBook Air 26.6.2 Chrome, iPhone 15 iOS 26.6.1
App Component: Left Hand Navigation (LHN)
Action Performed:
Expected Result:
Not here page is not shown
Actual Result:
"Not here" page appears when copilot opens WS chat, switches account back to their own account and goes to Inbox
Workaround:
Unknown
Platforms:
Screenshots/Videos
Bug7271815_1790619249143.Not_here.mp4
View all open jobs on GitHub
Upwork Automation - Do Not Edit