Skip to content

[$175] Copilot-Not here page appears when copilot opens WS chat, switches account and goes to Inbox #102441

Description

@applause-bot

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:

  1. As User A, add User B as a copilot
  2. As User A, create a workspace
  3. As User B, switch to User A's account in Account tab
  4. Go to Inbox, open workspace chat
  5. Go to Account tab and switch back to the own account
  6. Open Inbox

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:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome Safari

Screenshots/Videos

Bug7271815_1790619249143.Not_here.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Svetlana Lazutkina
Bug ID: 7271815

Upwork Automation - Do Not Edit

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Sep 28, 2026
  2. applause-bot commented on Sep 28, 2026

    @applause-bot
    Author

    While Applause doesn't embed attachments for this bug, here are the links for quick view:
    https://platform.applause.com/services/links/v1/external/ef8f4f96530d5f11206537315f468abb8b5935372ef1953863daddcca27b7f3b

  3. MelvinBot commented on Sep 28, 2026

    @MelvinBot
    Contributor

    Proposal

    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() and disconnect() in Delegate.ts call only clearPreservedSearchNavigatorStates(). That function drops only the Search tab's saved state. The Inbox (Reports) split navigator keeps the other account's REPORT route.
    • When the user taps Inbox, InboxTabButton finds that the saved report no longer exists in Onyx. It falls back to Navigation.navigate(ROUTES.INBOX).
    • On wide layout, SplitRouter ignores a "push sidebar" action and keeps the current central screen. The stale report stays open.
    • The user has no access to that report, so ReportNotFoundGuard shows the not-found page.
    Code references

    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.

    1. Call clearPreservedNavigatorStates() instead of clearPreservedSearchNavigatorStates().
    2. On web, clear the LAST_VISITED_PATH sessionStorage keys used to restore the Workspaces tab.
    3. 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 remount ReportsSplitNavigator, so it drops the stale initial reportID too.

    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 WideInboxTabButton so it replaces the central REPORT screen instead of calling Navigation.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

    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.


    view run

  4. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Sep 28, 2026
  5. melvin-bot commented on Sep 28, 2026

    @melvin-bot

    Triggered auto assignment to Contributor-plus team member for initial proposal review - @eh2077 (External)

  6. 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
  7. melvin-bot commented on Sep 28, 2026

    @melvin-bot
  8. ashusatyarthi-wq commented on Sep 28, 2026

    @ashusatyarthi-wq

    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() or disconnect() in src/libs/actions/Delegate.ts), Onyx data for the previous account is cleared via clearOnyxForDelegateTransition(). However, the navigation state is not properly reset:

    1. Delegate.ts only invokes Navigation.clearPreservedSearchNavigatorStates() rather than clearing all preserved navigator states:

      • clearPreservedSearchNavigatorStates() only purges preserved route state for the Search tab navigator.
      • The ReportsSplitNavigator retains the previous account's active REPORT route (User A's workspace chat reportID) in its preserved state.
    2. When the user taps the Inbox tab after switching back to their account:

      • InboxTabButton detects that the saved reportID no longer exists in Onyx for User B and falls back to Navigation.navigate(ROUTES.INBOX).
      • On wide layouts, SplitRouter does not dismiss or reset the central screen when navigating to the sidebar root (ROUTES.INBOX), keeping the stale REPORT route active.
      • Because the report belongs to User A and no longer exists in User B's Onyx store, ReportNotFoundGuard triggers and displays the "Hmm... it's not here" screen.

    What changes do you think we should make in order to solve the problem?

    1. Clear All Preserved Navigator States on Delegate Switch:
      In src/libs/actions/Delegate.ts:
      Replace calls to clearPreservedSearchNavigatorStates() with clearPreservedNavigatorStates() in both connect() and disconnect() so that cached split-navigator states (including ReportsSplitNavigator) are cleared across delegate boundaries:

      // In Delegate.ts (connect & disconnect)
      Navigation.clearPreservedNavigatorStates();
    2. Reset Navigation to App Root on Delegate Transition:
      Similar to the sign-out/session transition in NavigationRoot.tsx, reset navigation state upon completing connect() and disconnect():

      Navigation.resetToAppRoot();

      This ensures that the tab bar and split navigators remount with fresh route keys and without stale lastAccessedReportID references from the previous session.

    3. Fallback in SplitRouter / InboxTabButton:
      In src/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 to ROUTES.HOME / first available report rather than leaving the inaccessible report mounted.


    What alternative solutions did you explore? (Optional)

    • Relying solely on ReportNavigateAwayHandler: ReportNavigateAwayHandler checks if the report is missing, but when unfocused or transitioning during account reload, it can fail to redirect before the ReportNotFoundGuard mounts. A full navigation reset alongside clearPreservedNavigatorStates() addresses the root cause deterministically.

    Contributor details:
    Your Expensify account email: ashusatyarthi@gmail.com
    Upwork Profile Link: https://www.upwork.com/freelancers/~010e53044b5828fe60

  9. bonnhatnguyen commented on Sep 28, 2026

    @bonnhatnguyen
    ## 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() and disconnect() / restoreDelegateSession()):

    1. Incomplete navigator state cleanup:
      Lines 12, 137, and 201 call clearPreservedSearchNavigatorStates():

      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 with NAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR.
      However, it completely ignores all other split navigators, most notably ReportsSplitNavigator (NAVIGATORS.REPORTS_SPLIT_NAVIGATOR).
      As a result, preservedNavigatorStates in usePreserveNavigatorState.ts retains the entire route state of ReportsSplitNavigator, including User A's active workspace chat reportID.

    2. 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, restoreTabNavigatorRoutes reattaches the cached ReportsSplitNavigator state from preservedNavigatorStates.
      • On wide layouts, the split navigator attempts to mount the central REPORT screen with User A's workspace chat reportID.
      • Because that workspace chat belonged to User A and does not exist in User B's Onyx store, ReportNotFoundGuard (or ReportScreen) triggers and renders the "Hmm... it's not here" error page.

    In contrast, full logout in src/libs/Navigation/NavigationRoot.tsx (lines 140–145) explicitly calls clearPreservedNavigatorStates():

    // 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?

    1. In src/libs/actions/Delegate.ts:
      Replace clearPreservedSearchNavigatorStates() with clearPreservedNavigatorStates() in both connect() and disconnect() / 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;
    2. Reset Navigation root state on delegate transition:
      In src/libs/actions/Delegate.ts, call Navigation.resetToAppRoot() (or Navigation.reset(getStateToResetAfterLogout(navigationRef.getRootState()))) after clearOnyxForDelegateTransition(). This forces all tab split navigators to remount with clean initial routes, dropping stale lastAccessedReportID references from the previous user.

    3. In src/libs/Navigation/AppNavigator/createSplitNavigator/usePreserveNavigatorState.ts:
      Deprecate/remove the now redundant clearPreservedSearchNavigatorStates export in favor of canonical clearPreservedNavigatorStates.

    4. Automated Unit Tests:
      In tests/unit/actions/DelegateTest.ts:

      • Mock usePreserveNavigatorState's preservedNavigatorStates with mock states for REPORTS_SPLIT_NAVIGATOR and SEARCH_FULLSCREEN_NAVIGATOR.
      • Call connect() / disconnect() and verify clearPreservedNavigatorStates() is called, asserting preservedNavigatorStates is 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.

    What alternative solutions did you explore? (Optional)

    • Selectively clearing only REPORTS_SPLIT_NAVIGATOR and SEARCH_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

  10. melvin-bot commented on Sep 28, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  11. melvin-bot commented on Oct 1, 2026

    @melvin-bot

    @eh2077 Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

  12. ashusatyarthi-wq commented on Oct 2, 2026

    @ashusatyarthi-wq

    Contributor details
    Your Expensify account email: ashusatyarthi@gmail.com
    Upwork Profile Link: https://www.upwork.com/freelancers/~010e53044b5828fe60

  13. melvin-bot commented on Oct 2, 2026

    @melvin-bot

    ✅ Contributor details stored successfully. Thank you for contributing to Expensify!

  14. melvin-bot commented on Oct 5, 2026

    @melvin-bot

    @eh2077 Still overdue 6 days?! Let's take care of this!

  15. melvin-bot commented on Oct 7, 2026

    @melvin-bot

    @eh2077 8 days overdue is a lot. Should this be a Weekly issue? If so, feel free to change it!

  16. eh2077 commented on Oct 8, 2026

    @eh2077
    Contributor

    not reproducible, @MelvinBot please help check again

  17. MelvinBot commented on Oct 8, 2026

    @MelvinBot
    Contributor

    eh2077 I re-checked the code on current main and 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:

    1. Use a wide layout (desktop web or desktop). On a narrow layout, tapping Inbox returns to the chat list.
    2. 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.
    3. Make sure User B is not a member of User A's workspace. Otherwise the chat loads normally.
    4. Leave that chat open, switch back from the Account tab, then tap Inbox. Don't refresh or open another chat first.
    5. Expect a brief loading screen, then "Hmm... it's not here."
    Why it still happens on current main

    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.


    view run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

BugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributor

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions