Skip to content

Rules - Auto - Unable to import Merchant Rules offline #101411

Closed

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.81-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: https://test-management.browserstack.com/projects/2219752/test-runs/74236219/folder/13176708/131360173/1766787862?sort=%2Bidentifier
Email or phone of affected tester (no customers): applausetester+dk61@applause.expensifail.com
Issue reported by: Applause Internal Team
Bug source: Regression TC Execution
Device used: Windows 11 Home/Chrome
App Component: Workspace Settings

Action Performed:

Preconditions:

  • Create workspace and enable Rules
  1. Open https://staging.new.expensify.com/
  2. Go to Workspace settings
  3. Open Rules tab
  4. Go offline
  5. Click 'More' button
  6. Click 'Import merchant rules'
  7. Upload a csv file
  8. Set Merchant to Merchant is, Category to Updated category, and Description to Ignore
  9. Click 'Import' button

Expected Result:

Verify the offline import state is handled properly without application errors

Actual Result:

'Import' button is disabled, unable to click

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug7262290_1789637083762.Unable_to_import_merchant_rules_offline.mp4

View all open jobs on GitHub

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

Issue OwnerCurrent Issue Owner: @truph01

Activity

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

  3. changed the title [-]Rules-Auto- Unable to import Merchant Rules offline[/-] [+]Rules - Auto - Unable to import Merchant Rules offline[/+] on Sep 17, 2026
  4. MelvinBot commented on Sep 17, 2026

    @MelvinBot
    Contributor

    Proposal

    What is the root cause of that problem?

    The disabled Import button is intentional — merchant rules can't be created offline because the import needs a non-retryable API call. The actual bug is that merchant rules is the only import flow that lets you walk into the mapping page while offline, so it's the only one where you reach a silently greyed-out button with no explanation.

    Every comparable flow blocks navigation at the entry point with an explicit "You appear to be offline." modal. Merchant rules doesn't:

    Once you're on the page, the button is correctly disabled but gives zero feedback: ImportSpreadsheetColumns.tsx:118 sets isDisabled on a plain Button — no tooltip, no inline message, no FormAlertWithSubmitButton. Tapping it or pressing Enter does nothing at all.

    Supporting evidence

    The offline gate is deliberate and correct. ImportedMerchantRulesPage.tsx:332 computes canImportOffline, true only when the import short-circuits entirely client-side (every row skipped as a duplicate/unknown category). It's passed through as shouldDisableButtonWhenOffline={!canImportOffline}. In the QA repro the CSV produces net-new rules, so canImportOffline is false and the button is disabled — working as designed.

    Not a merchant-rules regression. shouldDisableButtonWhenOffline defaults to true (ImportSpreadsheetColumns.tsx:56) and grep -rn shouldDisableButtonWhenOffline src/ matches only this page and the component itself. All seven other consumers (categories, tags, multi-level tags, members, per-diem, company cards, wallet transactions) inherit true and are also disabled offline. Keep merchant rules import button active offline for the all-skipped path only relaxed the previously unconditional isDisabled={isOffline}.

    The only offline feedback on screen is the generic You appear to be offline. banner from ScreenWrapper, rendered below the footer button and identical on every screen — it never connects itself to the Import button.

    Alternative explanations ruled out: not a validation failure (validation only runs on submit and the QA mapping satisfies hasMerchantFilterColumn + hasActionColumn); not a loading/parse failure (the page rendered the mapping UI, so the spreadsheet parsed); not an unloaded-categories problem (areCategoriesReady only narrows canImportOffline, it can't disable an already-enabled button).

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

    Add an offline guard to the merchant-rules import entry point in getImportMerchantRulesOption.ts, matching what categories/tags/members/per-diem already do: when isOffline, show the common.youAppearToBeOffline / common.thisFeatureRequiresInternet confirm modal and don't navigate. This requires threading isOffline and a showOfflineModal callback in from PolicyRulesPageRevamp.tsx, the same way showReadOnlyModal is already passed.

    The offline user then gets a clear reason instead of a dead button, and the flow behaves like every other spreadsheet import.

    What alternative solutions did you explore? (Optional)

    • Surface an inline offline message next to the disabled button in ImportSpreadsheetColumns (switch to FormAlertWithSubmitButton with an offline message, or add a tooltip). This fixes the silent-disabled UX for all eight import flows at once, not just merchant rules. Better long-term, larger blast radius — worth doing in addition if we want consistency.
    • Do nothing / close as by-design. Defensible on strict behavior grounds, but the issue's expected result is "the offline import state is handled properly" and an unexplained dead button isn't that.
    • Note: WorkspaceCompanyCardsSettingsPage.tsx:200-215 has the same unguarded entry point and would need the same treatment.

    Possibly related


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


    view run

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

    @melvin-bot

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

  7. melvin-bot commented on Sep 17, 2026

    @melvin-bot

    Unable to auto-create job on Upwork. The BZ team member should create it manually for this issue.

  8. truph01 commented on Sep 18, 2026

    @truph01
    Contributor

    Expected: Verify the offline import state is handled properly without application errors

    @jponikarchuk Could you give me more detail about this expected behavior?
    Currently, the CTA button is disabled, I think it is fine.

  9. jponikarchuk commented on Sep 18, 2026

    @jponikarchuk

    @truph01 We have such steps in the TC

    Image
  10. melvin-bot commented on Sep 21, 2026

    @melvin-bot

    @truph01 Whoops! This issue is 2 days overdue. Let's get this updated quick!

  11. melvin-bot commented on Sep 23, 2026

    @melvin-bot

    @truph01 Eep! 4 days overdue now. Issues have feelings too...

  12. 3 remaining items

  13. melvin-bot commented on Oct 1, 2026

    @melvin-bot

    @truph01 this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

  14. melvin-bot commented on Oct 5, 2026

    @melvin-bot

    @truph01 Eep! 4 days overdue now. Issues have feelings too...

  15. truph01 commented on Oct 7, 2026

    @truph01
    Contributor

    @truph01 We have such steps in the TC
    Image

    @jponikarchuk It looks like your test case comes from #96976, right?

    I followed the test case in #96976 and it works well.

    @jponikarchuk Do you have any feedback on this comment? Are we good to close this issue?

  16. melvin-bot commented on Oct 12, 2026

    @melvin-bot

    @truph01 Huh... This is 4 days overdue. Who can take care of this?

  17. melvin-bot commented on Oct 14, 2026

    @melvin-bot

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

  18. melvin-bot commented on Oct 15, 2026

    @melvin-bot

    @truph01 this issue is now 4 weeks old, please consider:

    • Finding a contributor to fix the bug
    • Closing the issue if BZ has been unable to add the issue to a VIP or Wave project
    • If you have any questions, don't hesitate to start a discussion in #expensify-open-source

    Thanks!

  19. melvin-bot commented on Oct 16, 2026

    @melvin-bot

    @truph01 Now this issue is 8 days overdue. Are you sure this should be a Daily? Feel free to change it!

  20. truph01 commented on Oct 17, 2026

    @truph01
    Contributor

    Closed since it is not a bug

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