Skip to content

[Due for payment 2026-10-22] [$175] Copy WS settings stuck on "Copy in progress..." modal while offline #103297

Open

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.5.4-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: #102985
Email or phone of affected tester (no customers): jose.sat94+10jul@gmail.com
Issue reported by: Applause Internal Team
Bug source: Pull Request QA execution
Device used: MacBook Pro/13.7.8, Samsung Galaxy S21/Android 15, iPhone 13/18.6.2
App Component: Other

Action Performed:

  1. Launch Expensify app
  2. Log in with valid credentials
  3. Create a Control workspace (Workspace A)
  4. Enable Rules in Workspace A
  5. Create at least one merchant rule in Workspace A
  6. Create a Control workspace (Workspace C)
  7. Turn off Rules in Workspace C
  8. Click the ⋮ menu on Workspace A and select Copy settings
  9. Select Workspace C, click Next, tick Merchant rules, and click Next
  10. Click Copy settings
    The same when go offline after step 7.

Expected Result:

The copy settings process completes successfully, and Workspace C has Rules enabled with the merchant rule from Workspace A copied under Rules > Merchants.

Actual Result:

A "Copy in progress..." modal remains indefinitely with a loading spinner and the message "You can either wait for the process to finish or Concierge can let you know when it's done." The copy process does not complete.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

bandicam.2026-10-07.11-56-47-284.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Julia Ponikarchuk
Bug ID: 7279540

Upwork Automation - Do Not Edit
Issue OwnerCurrent Issue Owner: @mallenexpensify

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 7, 2026
  2. applause-bot commented on Oct 7, 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/07af7b371a65e768ceebc272dcdc3f09e8ee383f41edff7927c713b3426474b4

  3. changed the title [-]Offline - Copy WS settings stuck on "Copy in progress..." modal while offline[/-] [+]Copy WS settings stuck on "Copy in progress..." modal while offline[/+] on Oct 7, 2026
  4. MelvinBot commented on Oct 7, 2026

    @MelvinBot
    Contributor

    Proposal

    Updated 2026-10-10: Updated to follow Design's direction from dannymcclain. When you're offline, the copy now goes straight to "Concierge will let you know".

    Please re-state the problem that we are trying to solve in this issue.

    If you start Copy settings while offline, the "Copy in progress..." spinner loads indefinitely. Instead, it should go straight to "Concierge will let you know", since the copy can't finish until you're back online.

    What is the root cause of that problem?

    The App always opens the modal on the loading step. It sets currentStep: 'loading' in optimistic data (CopyPolicySettings.ts:550-557). That step only ends when the server sets nvp_bulkPolicyCopySettings to complete or failed (CopyPolicySettingsProgressModal.tsx:33-48). Offline, the request is only queued, so that update can't arrive. The confirm page doesn't check the network before it starts the copy (CopyPolicySettingsConfirmPage.tsx:95).

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

    When the copy starts offline, do what "Let me know when it's done" does today (CopyPolicySettingsProgressModal.tsx:106-109). Queue the Concierge notification and open the complete step.

    1. In CopyPolicySettingsConfirmPage.tsx, get isOffline from useNetwork() and pass it to copyPolicySettings.
    2. In buildCopyPolicySettingsData and copyPolicySettings (CopyPolicySettings.ts:365, 576-592), add an isOffline parameter. Then:
      • Set the optimistic currentStep to COPY_SETTINGS_MODAL_STEP.COMPLETE when offline. Keep LOADING when online.
      • When offline, call requestCopyPolicySettingsNotification() right after the CopyPolicySettings write. The sequential queue sends it after the copy request when you reconnect, the same order as the online "Let me know" flow.
    3. Keep everything else as it is, including the pending fields on the target workspaces and the failureData that resets currentStep and adds the error to the source workspace.

    The modal then shows "Concierge will let you know" with "When the process is completed, Concierge will send you a message." It has "Go to Concierge" and "Dismiss" buttons, so you aren't stuck.

    What specific scenarios should we cover in automated tests?

    In tests/actions/CopyPolicySettingsTest.ts:

    • If isOffline is true, the optimistic currentStep is complete, and the target policy patch and pending fields are still set.
    • If isOffline is false, the optimistic currentStep is still loading.
    • If copyPolicySettings runs offline, it queues CopyPolicySettings_Notify with shouldOnlyNotifyOnFailure: false after CopyPolicySettings. If it runs online, it doesn't queue the notification.

    What alternative solutions did you explore? (Optional)

    • Hide the modal when offline (my earlier proposal). Design prefers the Concierge step, because it tells you what will happen next.
    • Show "All set" when offline. This is wrong, because the copy hasn't run yet.
    • Switch steps inside the modal based on useNetwork(). This would also have to send the notification from a render path. It would also flip the step if you lose connection during an online copy. Deciding in the action when the copy starts avoids both problems.
    Evidence that the offline notification works

    In my 2026-10-08 web retest, I started the copy offline and clicked "Let me know when it's done" while still offline. After reconnecting, the queued copy ran. WS D got the merchant rule, and Concierge and #admins posted "copied 1 merchant rule from WS A". So queuing CopyPolicySettings_Notify offline, after the copy request, already works. This proposal makes that the automatic offline path.


    Next Steps for Contributor+ team:
    To accept: @MelvinBot implement [this](https://github.com/Expensify/App/issues/103297#issuecomment-6035029774) to create a draft PR.
    To refine: @MelvinBot <your feedback>
    To reject: Explain why you are rejecting Melvin's proposal.

  5. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Oct 7, 2026
  6. melvin-bot commented on Oct 7, 2026

    @melvin-bot

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

  7. changed the title [-]Copy WS settings stuck on "Copy in progress..." modal while offline[/-] [+][$175] Copy WS settings stuck on "Copy in progress..." modal while offline[/+] on Oct 7, 2026
  8. melvin-bot commented on Oct 7, 2026

    @melvin-bot
  9. camesenin commented on Oct 7, 2026

    @camesenin

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    When copying workspace settings (such as Merchant rules) to a workspace where Rules are disabled, the "Copy in progress..." modal remains stuck indefinitely with a loading spinner both online and while offline.

    What is the root cause of that problem?

    1. Missing Completion Transition in successData (CopyPolicySettings.ts):
      In src/libs/actions/Policy/CopyPolicySettings.ts:544-565, buildCopyPolicySettingsData sets NVP_BULK_POLICY_COPY_SETTINGS to in-progress optimistically, but successData intentionally omits setting it to complete, relying exclusively on an asynchronous backend Pusher broadcast:
      // Success intentionally omits this key — the backend transitions the bulk policy
      // copy NVP state to complete, which the UI uses to show the completion modal.
      For settings like codingRules (merchant rules), the CopyPolicySettings API call executes and returns HTTP 200 successfully, but the backend does not trigger the bulk NVP worker nor emit a Pusher broadcast for nvp_bulkPolicyCopySettings. Because CopyPolicySettingsProgressModal.tsx:44-46 requires bulkPolicyCopySettings?.state === CONST.POLICY.COPY_SETTINGS_NVP_STATE.COMPLETE to transition to "All Set", the modal remains trapped in loading indefinitely.
    2. Blocking Modal Lock While Offline:
      When initiated offline, the write is queued in SequentialQueue, but CopyPolicySettingsProgressModal immediately mounts on WorkspacesListPage with isTitleLoading: true and no dismiss/cancel option (shouldShowCancelButton: false, cancelText: ''), trapping the user behind an indefinite spinner without connectivity.

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

    1. Ensure successData Transitions the Modal to Complete:
      In src/libs/actions/Policy/CopyPolicySettings.ts, add the completion state to successData:
      successData.push({
          onyxMethod: Onyx.METHOD.MERGE,
          key: ONYXKEYS.NVP_BULK_POLICY_COPY_SETTINGS,
          value: {state: CONST.POLICY.COPY_SETTINGS_NVP_STATE.COMPLETE},
      });
      This guarantees that once the API request successfully resolves with HTTP 200, the UI transitions cleanly to "All set" without hanging on a missing backend Pusher echo.
    2. Improve Offline Progress Modal Dismissal:
      In src/pages/workspace/copyPolicySettings/CopyPolicySettingsProgressModal.tsx, enable dismissing the in-progress step via shouldShowCancelButton: true / cancel button or dismiss icon while offline/in-flight, ensuring the user is not locked behind a non-dismissible spinner when requests are queued offline.

    What alternative solutions did you explore? (Optional)

    • Waiting solely for a backend/Auth fix:
      Relying entirely on a server Pusher broadcast leaves the client vulnerable to missed socket messages and hanging spinners. Handling the API success transition in successData follows standard NewDot optimistic write patterns and makes the completion modal resilient.

    Contributor details
    Your Expensify account email: camesenin@gmail.com
    Upwork Profile Link: https://www.upwork.com/freelancers/~0170d6b02e9440e604

  10. melvin-bot commented on Oct 7, 2026

    @melvin-bot

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

  11. yuvrajangadsingh commented on Oct 8, 2026

    @yuvrajangadsingh
    Contributor

    withdrawing this, it went up before the issue had the Help Wanted label. will come back if the label is added.

  12. QichenZhu commented on Oct 8, 2026

    @QichenZhu
    Contributor

    @MelvinBot I don't agree this is a backend issue. This is clearly a frontend issue because the bug only happens in offline mode.

  13. 36 remaining items

  14. added
    Awaiting PaymentAuto-added when associated PR is deployed to production
    and removed on Oct 21, 2026
  15. melvin-bot commented on Oct 21, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

  16. melvin-bot commented on Oct 21, 2026

    @melvin-bot

    Payment Summary

    Resolving PRs:

    BugZero Checklist (@mallenexpensify)

    • I have confirmed assignees, roles, and Upwork contracts look correct
    • I have paid out Upwork contracts / manual NewDot requests
    • [BugZero Assignee] I have created a GH issue for creating/updating the regression test once above steps have been agreed upon
  17. mallenexpensify commented on Oct 24, 2026

    @mallenexpensify
    Contributor

    Payment Summary

    Contributor+: @QichenZhu due $100 via NewDot

    Tests weren't needed on the PR, standard amount is 50%

  18. QichenZhu commented on Oct 24, 2026

    @QichenZhu
    Contributor

    @mallenexpensify, testing was needed. MelvinBot didn't include test steps, but the OP and I did. If testing weren't needed, I would have marked the PR "No QA".'

    Update: I see what you mean: there's no reviewer checklist in the PR. That's really weird. I'm checking why.

    Update: I think I forgot to post the PR reviewer checklist. Sorry about that.

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

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething 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