Skip to content

[$175] Rate page closes without displaying "over the limit" error #105104

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: v9.5.21-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: #101685
Email or phone of affected tester (no customers): gd868gd+33@gmail.com
Issue reported by: Applause Internal Team
Bug source: Pull Request QA execution
Device used: Desktop / Windows 11, iPhone 15 Pro / iOS 27.0.1, Google Pixel 7a / Android 17
App Component: Chat Report View

Action Performed:

Preconditions:

  • Create a workspace and enable "Rules" and "Distance rates" in the "More features" section.
  • Add a rule that flags expenses over a certain amount.
  • Add a couple of different rates (one that will make an expense exceed the limit, and another one that wouldn't).
  • Manually create and submit a "Track distance" expense and apply a rate that will not make the expense exceed the limit.
  1. Open the Expensify Web App and log in
  2. Go to Spend / Expenses and open the expense from the Precondition
  3. Click on the "Rate" field and click on the rate that will make the expense exceed the limit
  4. Click on Save

Expected Result:

An error message should appear, and the page should stay open.

Actual Result:

The page closes without displaying the error.
The error appears on the expense RHP.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Bug7297465_1793054433294.Expensify_PR101685_Web_Rate.mp4

View all open jobs on GitHub

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

Upwork Automation - Do Not Edit

Activity

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

  3. MelvinBot commented on Oct 27, 2026

    @MelvinBot
    Contributor

    Issue Analysis

    Root Cause: This looks like expected behavior, not a bug. The workspace rule "flag expenses over a certain amount" creates a soft overLimit violation. A violation flags the expense but never blocks saving, so the Rate page saves the rate and closes. The violation then shows on the expense, which is where violations belong.

    The Rate page shows its own error only when the total would pass the hard maximum amount, MAX_SAFE_AMOUNT (999,999,999,999 in cents). The test amounts are far below that.

    Recommended Fix: I don't recommend a code change. If the team wants the Rate page to warn about policy limits before saving, treat that as a design change, not a regression fix.

    Investigation details
    • The in-page error is a hard-limit check. selectDistanceRate() shows distanceAmountTooLargeReduceRate ("The total amount is too large. Lower the rate.") only when isDistanceAmountWithinLimit() fails: DynamicIOURequestStepDistanceRate.tsx:204-208. That check compares the total to CONST.IOU.MAX_SAFE_AMOUNT: DistanceRequestUtils.ts:963-965, CONST/index.ts:4928. It never reads policy.maxExpenseAmount.
    • The workspace rule is a non-blocking violation. ViolationsUtils compares the amount to policy.maxExpenseAmount and adds an OVER_LIMIT violation with type: VIOLATION: ViolationsUtils.ts:957-969, ViolationsUtils.ts:1071-1084. The violation shows on the expense as "Amount over {limit}/person limit", which matches the "Actual Result" video.
    • The Save button did not change this. Gate IOU distance rate and vendor edit selection behind a Save button (a11y On Input, PR 14) only moved selectDistanceRate() from row tap to Save. Validation runs in the same order as before. Before that PR, tapping an over-policy-limit rate also saved and closed the page. The bug report also says production reproduces the issue.
    • Other explanation I checked: The Rate page might be failing to show the hard-limit error after the Save change. I ruled this out. When the hard limit fails, selectDistanceRate() returns early and the page stays open. onSelectRow clears the error only on the next row tap.
    • Not tested in the app. These findings come from reading the code. The repro needs a workspace with Rules and Distance rates set up, and I did not run it.

    Next Steps: If you agree this is expected, close the issue. If you want policy-limit warnings on the Rate page, reply with @MelvinBot <your feedback> and I'll scope that change.


    view run

  4. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Oct 27, 2026
  5. j3ffffff commented on Oct 27, 2026

    @j3ffffff

    VERDICT: POST
    ROOT_CAUSE_ONELINER: selectDistanceRate() only guards against the backend WAF overflow limit (~$10 billion), not workspace "max expense amount" rules, so a rate that triggers a rule violation passes validation, saves, and navigates away before the error can be shown.
    PROPOSAL_TYPE: FIRST
    AUTOPOST_SAFE: YES

  6. melvin-bot commented on Oct 27, 2026

    @melvin-bot

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

  7. changed the title [-]Rate page closes without displaying "over the limit" error[/-] [+][$175] Rate page closes without displaying "over the limit" error[/+] on Oct 27, 2026
  8. melvin-bot commented on Oct 27, 2026

    @melvin-bot
  9. khizzcr7 commented on Oct 27, 2026

    @khizzcr7

    Proposal

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

    When a distance expense is edited to a rate that trips a workspace rule (expense over the limit), saving closes the Rate page without showing the error. The error only appears afterwards on the expense RHP, so the user never sees why the save did not take effect on the page where they acted.

    What is the root cause of that problem?

    The Rate page dismisses on save regardless of the outcome of the update. The over-limit violation is written to the expense's error/violation state, which the expense RHP renders, but the Rate page itself never reads or waits for that result before navigating away, so the error has nowhere to surface on the page that triggered it.

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

    1. Hold the Rate page open until the rate update resolves instead of dismissing on save unconditionally.
    2. If the update returns a violation error, render that error inline on the Rate page and keep the page open so the user can pick a different rate.
    3. Only dismiss the page on a clean save with no violation error, preserving the current behaviour for under-limit rates and for workspaces with no such rule.

    What alternative solutions did you explore? (Optional)

    Showing the error only as a toast on dismiss was rejected: it disappears, and the user is left on the expense RHP without the rate picker open to correct the value.

    What automated tests can you add to prevent this from re-occurring?

    • Saving an over-limit rate keeps the Rate page open with the error visible.
    • Saving an under-limit rate closes the page and persists the new rate.
    • Saving in a workspace with no over-limit rule closes the page exactly as before.
  10. camesenin commented on Oct 27, 2026

    @camesenin

    Proposal

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

    When editing the distance rate of a submitted expense to a value that causes the total amount to exceed a workspace policy rule limit, tapping Save dismisses the Rate page immediately without showing an error on that page, and the violation is only displayed afterwards on the expense details (RHP).

    What is the root cause of that problem?

    This is Expected Behavior (Working as Intended by Design) under Expensify's expense rule and violation architecture:

    1. Policy Rules Produce Non-Blocking Violations, Not Page Errors:
      In src/libs/Violations/ViolationsUtils.ts, rules such as "flag expenses over a certain amount" generate an overLimit violation. Violations in Expensify are non-blocking flags attached to the transaction for submitter/approver review; they do not prevent saving or editing expense fields.
    2. Rate Page Error Is Reserved for Hard Limits (MAX_SAFE_AMOUNT):
      In src/pages/iou/request/step/DynamicIOURequestStepDistanceRate.tsx (lines 204-208), the in-page error distanceAmountTooLargeReduceRate is triggered strictly by isDistanceAmountWithinLimit() (src/libs/DistanceRequestUtils.ts:963-965), which verifies against CONST.IOU.MAX_SAFE_AMOUNT (999,999,999,999 cents / WAF integer overflow guard). It deliberately does not block on workspace soft policy limits.
    3. Violations Belong to the Expense RHP:
      Dismissing the page and rendering the violation tag directly on the expense report/RHP is the standardized pattern across NewDot (categories, tags, and amounts).

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

    No code changes should be made to the client application.
    Attempting to block navigation on soft policy violations on the Rate page would:

    • Break consistency with all other expense edit steps (e.g. Category/Tag/Amount steps allow saving with soft rule warnings).
    • Prevent users from updating an expense when an approver has granted an exception.

    Recommended Action:

    1. Close this issue as Expected Behavior (NAB - Not A Bug).
    2. Update the regression test suite / BrowserStack test case documentation to clarify that policy violations are intended to surface on the expense RHP rather than halting navigation on the Rate selector.

    What alternative solutions did you explore? (Optional)

    • Blocking navigation on the Rate page until violations clear: Explored and rejected. Trapping the user on the Rate step contradicts the asynchronous violation resolution flow of Expensify.

    What automated tests can you add to prevent this from re-occurring?

    Verify in tests/unit/DistanceRequestUtilsTest.ts that saving a rate that triggers a policy rule persists the selected rate successfully and retains the violation on the transaction without throwing in-page blocking errors.

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

  11. melvin-bot commented on Oct 27, 2026

    @melvin-bot

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

  12. bernhardoj commented on Oct 27, 2026

    @bernhardoj
    Contributor

    @truph01 can you check if this is expected behavior?

  13. weaieverything commented on Oct 27, 2026

    @weaieverything

    Proposal

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

    During QA of PR #101685 (Add validation for distance expense rate), when a tester sets a workspace rule ("flag expenses over a certain amount") and selects a distance rate that exceeds that workspace rule limit, clicking Save on the Rate page closes the Rate page and shows the overLimit violation on the expense RHP rather than keeping the Rate page open with an in-page error.

    What is the root cause of that problem?

    This is expected behavior by design (a mismatch between the QA test setup and what PR #101685 validates):

    1. In-page Rate error in DynamicIOURequestStepDistanceRate.tsx only guards against CONST.IOU.MAX_SAFE_AMOUNT (999,999,999,999 cents / $9,999,999,999.99), not workspace policy rules:
      • In src/pages/iou/request/step/DynamicIOURequestStepDistanceRate.tsx:204-208, selectDistanceRate checks:
        if (!DistanceRequestUtils.isDistanceAmountWithinLimit(distanceInUnits, newRate)) {
            setPendingRateID(customUnitRateID);
            setFormError(translate('iou.error.distanceAmountTooLargeReduceRate'));
            return;
        }
      • In src/libs/DistanceRequestUtils.ts:963-965, isDistanceAmountWithinLimit(distance, rate) returns Math.abs(roundDistanceAmount(distance, rate)) <= CONST.IOU.MAX_SAFE_AMOUNT (12 digits in cents = 999,999,999,999 cents) to prevent backend WAF rejections.
    2. Workspace "flag expenses over a certain amount" rules (maxExpenseAmount) produce non-blocking overLimit transaction violations:
      • In src/libs/Violations/ViolationsUtils.ts, exceeding policy.maxExpenseAmount creates a soft CONST.VIOLATIONS.OVER_LIMIT violation on the transaction after saving (setMoneyRequestDistanceRate -> navigateBack()), which is rendered on the expense RHP and never blocks saving any expense field (Amount, Distance, or Rate).

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

    No code change is needed—this is expected behavior, and the BrowserStack regression test step for PR #101685 should test a distance + rate combination whose total exceeds $9,999,999,999.99 (CONST.IOU.MAX_SAFE_AMOUNT = 999,999,999,999 cents), not a workspace maxExpenseAmount rule violation.

    What alternative solutions did you explore?

    Blocking the Rate page on policy.maxExpenseAmount was considered, but workspace expense rules are soft compliance flags (overLimit violation) across all expense edit pages (Amount, Distance, Category) and are intentionally allowed to save.

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