Skip to content

[Due for payment 2026-05-29] [$250] Expenses - Unable to save the expense description field blank when it's required #88707

Closed

Description

@izarutskaya

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: 9.3.62-1
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from BrowserStack:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: @puneetlath
Slack conversation (hyperlinked to channel name): #expensify_bugs

Action Performed:

Precondition:

  • User has a Control Workspace with categories
  • Rules enabled
  • Description is required for some of categories

Steps:

  1. Go to https://staging.new.expensify.com/
  2. Go to workspace chat
  3. Create manual expense with category from precondition
  4. Open this expense > click description > try save without any changes

Expected Result:

User should save description without any changes

Actual Result:

User is unable to save the expense description field blank. It is flagging a violation.

Platforms:

Select the officially supported platforms where the issue was reproduced:

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

Screenshots/Videos

Recording.3724.mp4
Image

View all open jobs on GitHub

Issue OwnerCurrent Issue Owner: @mallenexpensify
Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~022047731679436458961
  • Upwork Job ID: 2047731679436458961
  • Last Price Increase: 2026-04-24

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    and removed
    BugSomething is broken. Auto assigns a BugZero manager.
    on Apr 24, 2026
  2. added
    BugSomething is broken. Auto assigns a BugZero manager.
    and removed
    BugSomething is broken. Auto assigns a BugZero manager.
    on Apr 24, 2026
  3. MelvinBot commented on Apr 24, 2026

    @MelvinBot
    Contributor

    Proposal

    What is the root cause of that problem?

    The validate function in IOURequestStepDescription.tsx:107-122 unconditionally blocks form submission when the description is required and empty. It doesn't account for the "no changes" case.

    The updateComment handler (line 147) correctly handles unchanged values by early-returning and navigating back — but FormProvider calls validate before onSubmit, so that early-return is never reached when the description is blank and required.

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

    In the validate callback in IOURequestStepDescription.tsx, skip the isDescriptionRequired check when the current value matches the original description (currentDescriptionInMarkdown). If the user hasn't changed anything, validation should not block saving.

    The check at line 115 should be updated to also verify the comment has actually changed from the original before enforcing the required-field rule:

    if (isDescriptionRequired && !values.moneyRequestComment && values.moneyRequestComment !== currentDescriptionInMarkdown)
    

    This way, if the description was already blank and the user didn't change it, the form submits normally and the existing early-return in updateComment navigates back as expected.

    What alternative solutions did you explore? (Optional)

    An alternative would be to bypass FormProvider validation entirely when the value is unchanged (e.g., a custom shouldValidate prop). However, that would be a larger change to the shared form infrastructure. The targeted fix in validate is simpler, scoped to this page, and preserves existing behavior for all other cases.

    Investigation details

    Data flow:

    1. User opens expense description (currently blank)
    2. User presses Save without changes
    3. FormProvider calls validate before onSubmit
    4. validate checks isDescriptionRequired (true) && !values.moneyRequestComment (true) → returns error
    5. Form shows "field required" and blocks submission
    6. updateComment (which has the unchanged-value early-return at line 147) is never called

    isDescriptionRequired source: CategoryUtils.ts:129-134 — returns true when the category has areCommentsRequired and policy rules are enabled.


    Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, @MelvinBot <your feedback> to refine this analysis, or explain why you are rejecting Melvin's proposal.

  4. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Apr 24, 2026
  5. added
    Help WantedApply this label when an issue is open to proposals by contributors
    on Apr 24, 2026
  6. melvin-bot commented on Apr 24, 2026

    @melvin-bot

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

  7. wildan-m commented on Apr 24, 2026

    @wildan-m
    Contributor

    Proposal

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

    On a Control workspace whose category has the "Description required" rule enabled, when a user opens an existing expense and taps the description menu item, the description step screen opens with the current (possibly empty) value pre-filled. Tapping Save without typing anything should simply close the step and return the user to the expense view — the description edit screen is not the place where a missing-description rule is enforced, that already happens on the expense/confirmation level via the missingComment violation. Today, the Save button surfaces a "This field is required" error on the input and blocks the user from leaving the step, even though nothing was changed.

    What is the root cause of that problem?

    The description step's form has two independent mechanisms that together are inconsistent:

    1. The form's onSubmit handler has an early return that already short-circuits the "nothing changed" case — if the trimmed submitted value equals the value the user opened the screen with, it just flips isSaved and navigates back without touching Onyx:

    };
    const updateComment = (value: FormOnyxValues<typeof ONYXKEYS.FORMS.MONEY_REQUEST_DESCRIPTION_FORM>) => {
    if (!transaction?.transactionID) {
    return;

    1. The form's validate callback, added when the "Description required" category rule landed, unconditionally flags the required error whenever the description is required for the category and the submitted value is empty — it never looks at what the user actually started with:

    }
    if (isDescriptionRequired && !values.moneyRequestComment) {

    Because FormProvider runs validate before calling onSubmit, the required-field error fires and the no-change shortcut in updateComment is never reached. As a result, any expense that already has an empty description (created before the rule was enabled, or whose category was changed after the fact, or simply opened to inspect it) becomes impossible to leave via Save — the user has to use the back arrow instead, which defeats the purpose of the Save button.

    The enforcement of the actual "description is required" policy rule lives in ViolationsUtils.getViolationsOnyxData and already surfaces a workspace-level violation on the expense regardless of whether the user saves a blank description, so relaxing this form-level guard only for the no-change path does not bypass the rule:

    !isInvoiceTransaction && policyCategories?.[categoryName ?? '']?.areCommentsRequired && !updatedTransaction.comment?.comment && isControlPolicy && policy?.areRulesEnabled;
    const rawAttendees = updatedTransaction.modifiedAttendees ?? updatedTransaction.comment?.attendees;

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

    In src/pages/iou/request/step/IOURequestStepDescription.tsx, make the validate callback consistent with the existing no-change shortcut in updateComment by skipping the required-field error when the submitted value is unchanged from currentDescriptionInMarkdown (both the current value that was displayed in the input and, after trimming, the submitted value). Concretely, inside validate, compute the trimmed submitted value once, and only add the common.error.fieldRequired error when the category requires a description AND the trimmed submitted value is empty AND the trimmed submitted value differs from currentDescriptionInMarkdown. Add currentDescriptionInMarkdown to the useCallback dependency array.

    This aligns the validator with the already-present "no-op save = navigate back" behavior in updateComment and keeps the character-limit check unchanged. It also leaves the case "user actively cleared a non-empty description on a required category" correctly rejected — in that case, the submitted value is empty but differs from the stored non-empty value, so the required error still fires.

    Compare branch: https://github.com/Expensify/App/compare/main...wildan-m:App:wildan/88707-allow-no-change-save-on-required-description?expand=1

    Creation flow is unaffected: when the category has the rule and the user reaches this step during manual expense creation, the stored description (the value used for the unchanged comparison) is empty, and if the user submits empty, the submitted trimmed value equals the stored empty value — validation would pass here, but the missing description is then caught on the confirmation list where isDescriptionRequired is already wired into the submit guard:

    const isDescriptionRequired = useMemo(
    () => isCategoryDescriptionRequired(policyCategories, iouCategory, policy?.areRulesEnabled),
    [iouCategory, policyCategories, policy?.areRulesEnabled],
    );

    What alternative solutions did you explore? (Optional)

    An alternative was to move the required check out of the form validator entirely and into updateComment so that it runs after the no-change early return. That works but it splits validation between two places and loses the automatic inline error UX that FormProvider gives for free on the character-limit check — a user who did clear a required description would no longer see the red inline hint under the input, only a generic alert. Keeping the check in validate and simply widening its condition to value-is-empty AND value-changed-from-original preserves both UX paths with a minimal, local change.

  8. melvin-bot commented on Apr 24, 2026

    @melvin-bot
  9. changed the title [-]Expenses - Unable to save the expense description field blank when it's required[/-] [+][$250] Expenses - Unable to save the expense description field blank when it's required[/+] on Apr 24, 2026
  10. 65 remaining items

  11. mallenexpensify commented on Jun 1, 2026

    @mallenexpensify
    Contributor

    @karan-1302 can you please accept the job below? Please reply here and tag me once you have.
    https://www.upwork.com/jobs/~022060466163242179232

    Thx

  12. karan-1302 commented on Jun 3, 2026

    @karan-1302
    Contributor

    @mallenexpensify It says that the job is no longer available. Please take a look

  13. added and removed on Jun 3, 2026
  14. mallenexpensify commented on Jun 3, 2026

    @mallenexpensify
    Contributor

    @karan-1302 can you check again plz? Upwork's been having issues lately. I'm seeing on my end
    https://www.upwork.com/jobs/~022060466163242179232

    Image
  15. karan-1302 commented on Jun 4, 2026

    @karan-1302
    Contributor

    @mallenexpensify it is visible now and I’ve already applied for it before. So it says you’ve already submitted your proposal, could you take a look please?

  16. added and removed on Jun 4, 2026
  17. mallenexpensify commented on Jun 4, 2026

    @mallenexpensify
    Contributor

    @karan-1302 you need to accept the offer in Upwork in order for me to hire and pay. It's still showing 'pending'. Maybe see if this link works/helps?
    https://www.upwork.com/nx/wm/offer/111594726

  18. karan-1302 commented on Jun 5, 2026

    @karan-1302
    Contributor
  19. mallenexpensify commented on Jun 5, 2026

    @mallenexpensify
    Contributor

    @karan-1302 paid, summary updated above. Thx.

  20. JmillsExpensify commented on Jun 5, 2026

    @JmillsExpensify
    Contributor

    $250 approved for @gijoe0295

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