Skip to content

[Due for payment 2026-11-05] [$175] Workspaces - Unable to remove the RBR on archived Workspace #103492

Open

Description

@lanitochka17

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Version Number: v9.5.5-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: #98029
Email or phone of affected tester (no customers): applausetester+vq+0810@applause.expensifail.com
Issue reported by: Applause Internal Team
Bug source: Exploratory - Significant User Experience Deterioration
Device used: Windows 10/Chrome
App Component: Workspace Settings

Action Performed:

Precondition: User the Expensifail account as an admin of a Workspace

  1. Open the New Dot app
  2. Navigate to the Workspace - Accounting
  3. Connect to Sage Intacct - Enter incorrect credentials (to get an RBR )
  4. Go to Workspace - Three dots - Archived Workspace - Confirm

Expected Result:

RBR remove after the Workspace is archived

Actual Result:

RBR remains on the Workspace tab but can't remove it

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug7281217_1791465904352.accounting_RBR_-_.mp4

View all open jobs on GitHub

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

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 8, 2026
  2. MelvinBot commented on Oct 8, 2026

    @MelvinBot
    Contributor

    Proposal

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

    After you archive a workspace that has an accounting sync error, the Workspaces tab keeps its red dot (RBR). The archived workspace is hidden from the list and you can't edit its settings, so you can't clear the error.

    What is the root cause of that problem?

    Archiving keeps the workspace in Onyx. It only adds archivedDate. The Sage Intacct sync error stays on the policy (Policy.ts:744-786).

    The Workspaces tab RBR checks every policy that has an id. It never skips archived policies (usePoliciesWithCardFeedErrors.ts:15). So the HAS_SYNC_ERRORS check in usePolicyIndicatorChecks.ts:56-65 still finds the archived workspace and turns the tab red.

    The workspaces list hides archived policies through shouldShowPolicy, and canEditWorkspaceSettings blocks edits on them. That leaves the user no way to fix the error.

    This started with feat: Replace Delete with Archive behind the archivePolicies beta. Delete didn't have this problem because the server removes a deleted policy from Onyx.

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

    1. In usePoliciesWithCardFeedErrors, leave archived policies out of cleanPolicies with the existing isArchivedPolicy helper. Use isArchivedOrPendingDeletePolicy instead if you also want to hide errors while a delete is pending. Every Workspaces tab check reads cleanPolicies, so this one change fixes all of them.
    2. Optional, for consistency: in createPolicyErrorsSelector (WorkspaceRowBrickRoadIndicator.tsx:37-40), return false for archived policies. Otherwise the row still shows an RBR you can't fix when the "Archived" filter is on.
    3. Add a unit test: a policy with archivedDate and a failed Intacct sync should give no Workspaces tab indicator.

    Filter on the client, not by clearing the error on the backend. That way the error comes back if the workspace is unarchived.

    What alternative solutions did you explore? (Optional)

    Have ArchivePolicy clear connections.*.lastSync errors. I rejected this because unarchiving would hide a real, unresolved sync error.

    Investigation details
    • Chain for the tab color: WorkspacesTabButton → useWorkspacesTabIndicatorStatus → usePolicyIndicatorChecks → usePoliciesWithCardFeedErrors().cleanPolicies.
    • isArchivedPolicy is defined at PolicyUtils/index.ts:111-113. isArchivedOrPendingDeletePolicy is at PolicyUtils/index.ts:130-132.
    • Side effect: useAccountIndicatorChecks reads isPolicyAdmin from the same hook. After the change, card feed errors on an archived workspace will no longer hide the employee card feed RBR on the Account tab. That is probably correct. useCardFeedErrors may still count feeds from archived workspaces, so check it during the PR.
    • The workspace switcher (useWorkspaceList) already skips archived policies through shouldShowPolicy.
    • I found this by reading the code. I did not test it in the app.

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


    view run

  3. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Oct 8, 2026
  4. melvin-bot commented on Oct 8, 2026

    @melvin-bot

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

  5. changed the title [-]Workspaces - Unable to remove the RBR on archived Workspace[/-] [+][$175] Workspaces - Unable to remove the RBR on archived Workspace[/+] on Oct 8, 2026
  6. melvin-bot commented on Oct 8, 2026

    @melvin-bot
  7. 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.

  8. jloa-dev commented on Oct 8, 2026

    @jloa-dev

    Proposal

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

    The Red Brick Road (RBR) error indicator remains permanently visible on the Workspaces tab (and on the workspace row in the workspaces list) after a workspace with an accounting sync error (such as bad credentials) is archived, and the user has no way to dismiss or clear it because archived workspaces are read-only.

    What is the root cause of that problem?

    1. In src/hooks/usePoliciesWithCardFeedErrors.ts, cleanPolicies filters policies solely by whether they possess an id:
    const cleanPolicies = Object.values(policies ?? {}).filter((policy) => policy?.id);

    It does not filter out archived policies using isArchivedPolicy(policy).

    1. When usePolicyIndicatorChecks iterates through cleanPolicies to evaluate shouldShowSyncError (along with shouldShowPolicyError, shouldShowCustomUnitsError, shouldShowEmployeeListError, etc.), the archived workspace is still evaluated:
    [
        CONST.INDICATOR_STATUS.HAS_SYNC_ERRORS,
        cleanPolicies.find((cleanPolicy) =>
            shouldShowSyncError(
                cleanPolicy,
                isConnectionInProgress(allConnectionSyncProgresses?.[`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${cleanPolicy?.id}`], cleanPolicy),
                CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES,
            ),
        ),
    ]

    Because neither shouldShowSyncError nor cleanPolicies checks if the policy is archived, the hook returns HAS_SYNC_ERRORS, keeping the red dot visible in useWorkspacesTabIndicatorStatus.

    1. Similarly, in src/libs/PolicyUtils/index.ts, getPolicyBrickRoadIndicatorStatus lacks an early return check for isArchivedPolicy(policy), which causes WorkspaceRowBrickRoadIndicator.tsx to continue displaying the red indicator on the row even when the workspace is archived.

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

    1. In src/hooks/usePoliciesWithCardFeedErrors.ts:
      Exclude archived policies when generating cleanPolicies so usePolicyIndicatorChecks suppresses error indicators originating from read-only archived workspaces:
    import {isArchivedPolicy, isPolicyAdmin} from '@libs/PolicyUtils';
    
    // ...
    const cleanPolicies = Object.values(policies ?? {}).filter((policy) => policy?.id && !isArchivedPolicy(policy));
    1. In src/libs/PolicyUtils/index.ts:
      In getPolicyBrickRoadIndicatorStatus, return undefined immediately when the policy is archived:
    function getPolicyBrickRoadIndicatorStatus(policy: OnyxEntry<Policy>, isConnectionInProgress: boolean): ValueOf<typeof CONST.BRICK_ROAD_INDICATOR_STATUS> | undefined {
        if (isArchivedPolicy(policy)) {
            return undefined;
        }
    
        if (
            shouldShowEmployeeListError(policy) ||
            shouldShowCustomUnitsError(policy) ||
            shouldShowPolicyErrorFields(policy) ||
            shouldShowSyncError(policy, isConnectionInProgress, getAccountingConnectionNames()) ||
            shouldShowQBOReimbursableExportDestinationAccountError(policy) ||
            shouldShowHRConnectionError(policy, isConnectionInProgress, isPolicyAdmin(policy))
        ) {
            return CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR;
        }
        return undefined;
    }
    1. In src/components/Tables/WorkspaceListTable/WorkspaceRowBrickRoadIndicator.tsx:
      Add an archived check to createPolicyErrorsSelector:
    const createPolicyErrorsSelector = (connectionSyncProgress: OnyxEntry<PolicyConnectionSyncProgress>) => (policy: OnyxEntry<Policy>) =>
        !isArchivedPolicy(policy) &&
        (getUberConnectionErrorDirectlyFromPolicy(policy) ||
            shouldShowEmployeeListError(policy) ||
            getPolicyBrickRoadIndicatorStatus(policy, isConnectionInProgress(connectionSyncProgress, policy)) === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR);

    What alternative solutions did you consider?

    • Modifying each individual shouldShow*Error function to check !isArchivedPolicy(policy): this adds redundant checks across multiple utility functions instead of handling it centrally in cleanPolicies, getPolicyBrickRoadIndicatorStatus, and row selector.
    • Clearing error fields in Onyx when archiving a policy: this would be destructive and fragile if server responses or sync progress updates re-populate the error keys asynchronously.
  9. ashusatyarthi-wq commented on Oct 9, 2026

    @ashusatyarthi-wq

    Proposal

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

    When a workspace with an accounting sync error (such as invalid Sage Intacct credentials) is archived, the Red Brick Road (RBR) dot remains permanently visible on the Workspaces bottom tab. The user cannot dismiss or resolve the error because archived workspaces are read-only and hidden from standard active settings.

    What is the root cause of that problem?

    1. The global Workspaces tab indicator in usePolicyIndicatorChecks.ts evaluates all policy errors across cleanPolicies.
    2. cleanPolicies is provided by usePoliciesWithCardFeedErrors.ts:
      // src/hooks/usePoliciesWithCardFeedErrors.ts
      const cleanPolicies = Object.values(policies ?? {}).filter((policy) => policy?.id);
      It filters out only null policies that lack an id. It does not filter out archived policies (isArchivedPolicy(policy)).
    3. When a policy is archived, it remains in Onyx under ONYXKEYS.COLLECTION.POLICY with its errors intact and isArchived: true / archivedDate set.
    4. Because cleanPolicies continues to include archived policies, policyErrorChecks in usePolicyIndicatorChecks.ts flags CONST.INDICATOR_STATUS.HAS_SYNC_ERRORS via shouldShowSyncError for the archived workspace, keeping the global Workspaces tab RBR permanently lit.
    5. In addition, createPolicyErrorsSelector in WorkspaceRowBrickRoadIndicator.tsx does not check isArchivedPolicy(policy), which leaves the row indicator active on archived workspace rows.

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

    1. In src/hooks/usePoliciesWithCardFeedErrors.ts, import isArchivedPolicy from @libs/PolicyUtils and exclude archived policies from cleanPolicies:

      + import {isArchivedPolicy, isPolicyAdmin} from '@libs/PolicyUtils';
      ...
      - const cleanPolicies = Object.values(policies ?? {}).filter((policy) => policy?.id);
      + const cleanPolicies = Object.values(policies ?? {}).filter((policy) => policy?.id && !isArchivedPolicy(policy));

      This ensures that all global indicator checks in usePolicyIndicatorChecks.ts (sync errors, card feed errors, QBO export errors, employee list errors, custom units errors, etc.) ignore archived policies.

    2. In src/components/Tables/WorkspaceListTable/WorkspaceRowBrickRoadIndicator.tsx, guard createPolicyErrorsSelector against archived policies:

      + import {
      +     getPolicyBrickRoadIndicatorStatus,
      +     getUberConnectionErrorDirectlyFromPolicy,
      +     isArchivedPolicy,
      +     isMergeHRCompleteSetupNeededSelector,
      +     isQBORefreshTokenExpiringSoonSelector,
      +     shouldShowEmployeeListError,
      + } from '@libs/PolicyUtils';
      ...
      const createPolicyErrorsSelector = (connectionSyncProgress: OnyxEntry<PolicyConnectionSyncProgress>) => (policy: OnyxEntry<Policy>) =>
      +   !isArchivedPolicy(policy) &&
          (getUberConnectionErrorDirectlyFromPolicy(policy) ||
          shouldShowEmployeeListError(policy) ||
          getPolicyBrickRoadIndicatorStatus(policy, isConnectionInProgress(connectionSyncProgress, policy)) === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR);

    What specific scenarios should we cover in automated tests?

    1. In tests/unit/usePolicyIndicatorChecksTest.ts:
      • A workspace with accounting sync errors has an active policyErrorStatus of HAS_SYNC_ERRORS.
      • When the workspace is archived (isArchived: true / archivedDate set), policyErrorStatus becomes undefined and the RBR indicator is cleared.
    2. In tests/unit/usePoliciesWithCardFeedErrorsTest.ts:
      • Verify that cleanPolicies excludes archived policies.
    3. In tests/unit/WorkspaceRowBrickRoadIndicatorTest.tsx:
      • An archived workspace with sync errors returns no error indicator (hasPolicyErrors is false).
  10. ashusatyarthi-wq commented on Oct 9, 2026

    @ashusatyarthi-wq

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

  11. melvin-bot commented on Oct 9, 2026

    @melvin-bot

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

  12. cretadn22 commented on Oct 9, 2026

    @cretadn22
    Contributor

    I am unable to reproduce this issue

    Screen.Recording.2026-10-09.at.23.03.43.mov

    @MelvinBot Could you double-check root cause in your proposal? I'm unable to reproduce this on the latest main branch. Do we specifically need to use an expensifail account to trigger this bug?

  13. jloa-dev commented on Oct 9, 2026

    @jloa-dev

    @cretadn22 Yes, exactly! To reproduce the bug, the workspace must have an existing policy/accounting sync error in Onyx before it is archived:

    1. An @expensifail.com admin account is needed because it has access to the Sage Intacct accounting integration.
    2. Go to Workspace > Accounting > Sage Intacct and enter invalid credentials so the backend returns an error, setting the RBR error badge on the accounting connection.
    3. Then go to Workspace > Three dots > Archive Workspace > Confirm.
    4. Once archived, the child configuration tabs (like Accounting) are locked/hidden, preventing the user from dismissing or resolving the connection error. However, the workspace navigation row still evaluates hasPolicyError on the archived policy in Onyx, leaving the RBR badge permanently visible with no way to remove it.

    Without that initial failed connection (via the @expensifail.com test account) generating the error state prior to archiving, the workspace remains clean and won't surface an RBR.

  14. 5 remaining items

  15. melvin-bot commented on Oct 11, 2026

    @melvin-bot

    Triggered auto assignment to @deetergp, see https://stackoverflow.com/c/expensify/questions/7972 for more details.

  16. deetergp commented on Oct 12, 2026

    @deetergp
    Contributor

    @cretadn22 agreed. Feel free to run with it!

  17. changed the title [-][$175] Workspaces - Unable to remove the RBR on archived Workspace[/-] [+][Due for payment 2026-11-05] [$175] Workspaces - Unable to remove the RBR on archived Workspace[/+] on Oct 29, 2026
  18. melvin-bot commented on Oct 29, 2026

    @melvin-bot

    @cretadn22

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.25-2 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-11-05. 🎊

    The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]. If no checklist is needed for this issue, you can click: [no checklist button]

  19. cretadn22 commented on Oct 30, 2026

    @cretadn22
    Contributor

    BugZero Checklist:

    • [Contributor] The offending PR and associated issue have been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.

      Link to the comment on the PR: feat: Replace Delete with Archive behind the archivePolicies beta #98029 (comment)
      Link to the comment on the Issue: N/A

    • [Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.

      Link to discussion: N/A

    • [Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.

    • [BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.

      Link to issue:

    Regression Test Proposal

    Test:

    Precondition: Enable the archivePolicies beta flag.

    1. Open the New Dot app
    2. Navigate to Workspace > Accounting
    3. Connect to Sage Intacct using incorrect credentials (to trigger an RBR)
    4. Go to Workspace > Three dots > Archived Workspace > Confirm
    5. Verify that the RBR on the workspace is removed after it is archived
    6. Filter by archived workspaces
    7. Verify that the RBR on the workspace row is also removed

    Do we agree 👍 or 👎

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

Metadata

Metadata

Labels

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

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions