Skip to content

[Due for payment 2025-12-26] [$250] Distance Expense - Rate is not valid blinks #76771

Closed

Description

@vincdargento

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.2.71-2
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/TR-2264/folder/13176877/41237359/1054916534
Email or phone of affected tester (no customers): gocemate+sdfasdfasdfff@gmail.com
Issue reported by: Applause Internal Team
Device used: Lenovo 80ES / Windows 10 Pro
App Component: Other

Action Performed:

Preconditions: User is logged with gmail account, have Self DM and a Workspace

  1. Go to Self DM chat and create distance track map
  2. Select Do nothing
  3. Open the expense details page
  4. Click on header> Submit to someone
  5. Select the workspace

Expected Result:

"Rate not valid for this workspace. Please select an available rate from the workspace." should not blink

Actual Result:

"Rate not valid for this workspace. Please select an available rate from the workspace." blinks

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

bug.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021996773865971394579
  • Upwork Job ID: 1996773865971394579
  • Last Price Increase: 2025-12-05
Issue OwnerCurrent Issue Owner: @VictoriaExpensify

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Dec 4, 2025
  2. melvin-bot commented on Dec 4, 2025

    @melvin-bot

    Triggered auto assignment to @VictoriaExpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

  3. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Dec 5, 2025
  4. changed the title [-]Distance Expense - Rate is not valid blinks[/-] [+][$250] Distance Expense - Rate is not valid blinks[/+] on Dec 5, 2025
  5. melvin-bot commented on Dec 5, 2025

    @melvin-bot
  6. added
    Help WantedApply this label when an issue is open to proposals by contributors
    on Dec 5, 2025
  7. melvin-bot commented on Dec 5, 2025

    @melvin-bot

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

  8. VictoriaExpensify commented on Dec 5, 2025

    @VictoriaExpensify
    Contributor

    Yeah we should fix this, but it's a low priority I would say

  9. cretadn22 commented on Dec 5, 2025

    @cretadn22
    Contributor

    🚨 Edited by proposal-police: This proposal was edited at 2025-12-05 04:35:23 UTC.

    Proposal

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

    The message "Rate not valid for this workspace. Please select an available rate from the workspace." briefly appears and then disappears

    What is the root cause of that problem?

    The App sets formError here:

    setFormError(errorKey);

    After that, another part of the logic clears the error:

    Then the previous logic sets formError again, causing the blinking behavior.

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

    We should use debouncedFormError to display the error message and the red dot. Since debouncedFormError does not update immediately, it will consolidate multiple rapid updates into a single change and prevent the blinking.

    if (routeError) {
    return routeError;
    }
    if (isTypeSplit && !shouldShowReadOnlySplits) {
    return debouncedFormError && translate(debouncedFormError);
    }
    return formError && translate(formError);

            if (routeError) {
                return routeError;
            }
    
            return debouncedFormError && translate(debouncedFormError);
    

    And passing formError={debouncedFormError} to MoneyRequestConfirmationListFooter

    What alternative solutions did you explore? (Optional)

    Only clear the error when it matches specific cases:

    if (
        formError === 'iou.error.genericSmartscanFailureMessage' ||
        formError === 'iou.receiptScanningFailed'
    ) {
        setFormError('');
    }
    

    Or Using clearFormErrors(['iou.error.genericSmartscanFailureMessage', 'iou.receiptScanningFailed']);

    Reference to place:

  10. huult commented on Dec 5, 2025

    @huult
    Contributor

    Proposal

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

    "Rate not valid for this workspace. Please select an available rate from the workspace." blinks

    What is the root cause of that problem?

    This issue occurs only on the distance map flow, not on manual distance, because the manual distance flow does not trigger GetRouteForDraft.

    When I select a participant and navigate to the Money Request Confirmation screen, it triggers GetRouteForDraft to load the map distance.

    useFetchRoute(transaction, transaction?.comment?.waypoints, action, shouldUseTransactionDraft(action) ? CONST.TRANSACTION.STATE.DRAFT : CONST.TRANSACTION.STATE.CURRENT);

    keyPrefix = ONYXKEYS.COLLECTION.TRANSACTION_DRAFT;

    Screen.Recording.2025-12-05.at.13.14.10.mov

    Once the API responds, the transaction data is updated. Because of that update, the condition for setting the error message is triggered again when the transaction data finishes updating. Because the useEffect hook has transaction as a dependency. This is what causes the blinking.

    setFormError('');
    // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- we don't want this effect to run if it's just setFormError that changes
    }, [isFocused, transaction, shouldDisplayFieldError, hasSmartScanFailed, didConfirmSplit]);

    setFormError(errorKey);
    }, [
    isDistanceRequest,
    isPolicyExpenseChat,
    transactionID,
    mileageRate.rate,
    mileageRate.unit,
    customUnitRateID,
    policy,
    isMovingTransactionFromTrackExpense,
    setFormError,
    clearFormErrors,
    ]);

    This is transaction changed after we call GetRouteForDraft

    Screen.Recording.2025-12-05.at.13.20.21.mov

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

    To resolve this issue, we shouldn't update setFormError while GetRouteForDraft is loading. We should delay setting setFormError until GetRouteForDraft has finished.

    if (!transactionID || !isDistanceRequest || !isMovingTransactionFromTrackExpense || !isPolicyExpenseChat) {

    update to

            if (!transactionID || !isDistanceRequest || !isMovingTransactionFromTrackExpense || !isPolicyExpenseChat || transaction?.comment?.isLoading === true) {
    Screen.Recording.2025-12-05.at.13.19.11.mov

    What alternative solutions did you explore? (Optional)

    Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

  11. bernhardoj commented on Dec 5, 2025

    @bernhardoj
    Contributor

    Proposal

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

    Rate is not valid error blinks.

    What is the root cause of that problem?

    When the component mounts, we have this logic to clears the form error on mount.

    useEffect(() => {
    if (shouldDisplayFieldError && didConfirmSplit) {
    setFormError('iou.error.genericSmartscanFailureMessage');
    return;
    }
    if (shouldDisplayFieldError && hasSmartScanFailed) {
    setFormError('iou.receiptScanningFailed');
    return;
    }
    // reset the form error whenever the screen gains or loses focus
    setFormError('');
    // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- we don't want this effect to run if it's just setFormError that changes
    }, [isFocused, transaction, shouldDisplayFieldError, hasSmartScanFailed, didConfirmSplit]);

    And another effect that sets the invalid rate error.

    // If none of the above conditions are met, display the rate error
    setFormError(errorKey);

    But the first effect also clears the error when the transaction data changes.

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

    This commit adds the transaction to the deps because we use it inside the effect, but then we take it out and put it in a shouldDisplayFieldError variable but we don't remove the transaction object from the effect deps.

    Image

    So, we can remove transaction from the deps.

    useEffect(() => {
    if (shouldDisplayFieldError && didConfirmSplit) {
    setFormError('iou.error.genericSmartscanFailureMessage');
    return;
    }
    if (shouldDisplayFieldError && hasSmartScanFailed) {
    setFormError('iou.receiptScanningFailed');
    return;
    }
    // reset the form error whenever the screen gains or loses focus
    setFormError('');
    // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- we don't want this effect to run if it's just setFormError that changes
    }, [isFocused, transaction, shouldDisplayFieldError, hasSmartScanFailed, didConfirmSplit]);

  12. 21 remaining items

  13. melvin-bot commented on Dec 19, 2025

    @melvin-bot

    @bernhardoj @VictoriaExpensify The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero 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]

  14. melvin-bot commented on Dec 26, 2025

    @melvin-bot

    Payment Summary

    Upwork Job

    BugZero Checklist (@VictoriaExpensify)

    • (if NewFeature) I have created a PR for any necessary HelpDot updates, or I confirmed no updates are necessary.
    • I have verified the correct assignees and roles are listed above and updated the necessary manual offers
    • I have verified that there are no duplicate or incorrect contracts on Upwork for this job (https://www.upwork.com/ab/applicants/1996773865971394579/hired)
    • I have verified the PR was not reverted
    • I have applied any discounts due to bugs/regressions introduced by this PR
    • I have paid out the Upwork contracts or cancelled the ones that are incorrect
    • I have verified the payment summary above is correct
  15. melvin-bot commented on Jan 1, 2026

    @melvin-bot

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

  16. melvin-bot commented on Jan 2, 2026

    @melvin-bot

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

  17. VictoriaExpensify commented on Jan 5, 2026

    @VictoriaExpensify
    Contributor

    Payment Summary:
    C+: @sobitneupane owed $250 via NewDot
    C+: @bernhardoj owed $250 via NewDot

    Thanks!

  18. bernhardoj commented on Jan 5, 2026

    @bernhardoj
    Contributor

    Requested in ND.

  19. garrettmknight commented on Jan 31, 2026

    @garrettmknight
    Contributor

    $250 approved for @bernhardoj

  20. garrettmknight commented on Mar 16, 2026

    @garrettmknight
    Contributor

    $250 approved for @sobitneupane

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