You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[$175] Scheduled Submit - Retracting a report fails restore the workspace Scheduled Submit policy #104361
Version Number: v9.5.13-3 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/tc/TC-3464 Email or phone of affected tester (no customers):[email protected] Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: macOS 27.0.1 / Chrome 155, iOS 18.7.10 / iPhone XS App Component: Money Requests
Action Performed:
As Workspace Owner / Admin, navigate to Workspace Settings > Workflows
Enable Scheduled Submit and set the cadence to twice a month
As Employee, open or create an Open (unsubmitted) report in the workspace chat
Verify the Next Steps section displays: "Waiting for your expenses to automatically submit on the 1st and 16th of each month." and there's no GBR on the LHN
Manually Submit the report
Retract the submitted report so it returns to an Open status
Observe the "Next Steps" section and GBR in LHN
Expected Result:
After retracting the report back to Open status:
The "Next Steps" section should display: "Waiting for your expenses to automatically submit on the 1st and 16th of each month."
No manual green "Submit" button (GBR) should appear in the Left Hand Navigation
Actual Result:
Retracting the report breaks the Scheduled Submit state and reverts to a manual workflow. An optimistic UI flash briefly shows the correct auto-submit text before the final re-render overwrites it with "Waiting for you to submit expenses," while a "Submit" GBR incorrectly displays in the LHN.
Summary: The final state ("Waiting for you to submit expenses" plus a Submit GBR) matches how the App and the server treat retracted reports today. The real App bug is the short flash of the auto-submit text. That flash comes from retractReport building the wrong optimistic next step.
What is the root cause of that problem?
The flash.retractReport calls buildOptimisticNextStep without isReopen: true (ReportWorkflow.ts:708-718). Because of that, it falls into the harvesting branch and shows "automatically submit on the 1st and 16th". reopenReport does pass isReopen: true (ReportWorkflow.ts:544-555), which gives WAITING_TO_SUBMIT (NextStepUtils.ts:171-180).
The final text. The UI shows the stored report.nextStep. The RetractReport response replaces the optimistic value with WAITING_TO_SUBMIT.
What changes do you think we should make in order to solve the problem?
This depends on a product decision. An internal engineer needs to confirm whether backend Scheduled Submit picks up retracted reports.
If retracted reports need a manual submit (likely, since the server's next step says so): Pass isReopen: true to buildOptimisticNextStep in retractReport, the same way reopenReport does. This removes the flash. Add a retractReport unit test that checks the optimistic nextStep. The GBR and final text then stay as they are, by design.
If retracted reports should go back to Scheduled Submit: The backend must change the RetractReport next step and include retracted reports in harvesting. That change is outside the App repo, so escalate it to an internal engineer. After that, the App should apply the retracted/reopened override in shouldCurrentUserSubmitReport and ReportSecondaryActionUtils only when harvesting is off. An App-only change would conflict with the server's next step.
Investigation details
hasReportBeenRetracted checks the report field first, then any RETRACTED report action. Once set, the flag stays for the life of the report (ReportUtils.ts:14575-14601).
retractReport successData only clears pending fields and never writes nextStep. The overwrite therefore comes from the server's update.
The existing retractReport tests in tests/actions/IOUTest/ReportWorkflowTest.ts don't check nextStep.
I did not check backend harvesting behavior for retracted reports, so the product question above is still open.
Next Steps for Contributor+ team: To accept:@MelvinBot implement [this](https://github.com/Expensify/App/issues/104361) to create a draft PR. To refine:@MelvinBot <your feedback> To reject: Explain why you are rejecting Melvin's proposal.
changed the title [-]Scheduled Submit - Retracting a report fails restore the workspace Scheduled Submit policy[/-][+][$175] Scheduled Submit - Retracting a report fails restore the workspace Scheduled Submit policy[/+]on Oct 19, 2026
Please re-state the problem that we are trying to solve in this issue.
When retracting an expense report in a workspace configured with Scheduled Submit, an optimistic UI flash briefly displays auto-submit text before snapping to "Waiting for you to submit expenses" and rendering the green "Submit" button (GBR).
What is the root cause of that problem?
A mismatch between the optimistic NextStep builder and the server contract:
The Optimistic Flash: In src/libs/actions/IOU/ReportWorkflow.ts:708-718, retractReport calls buildOptimisticNextStep:
Notice that retractReport omits isReopen: true. Without this flag, buildOptimisticNextStep treats the open report as a standard auto-submitting draft and falls into the harvesting branch, optimistically flashing the scheduled auto-submit banner.
The Parity Contrast with reopenReport: In ReportWorkflow.ts:544-555, reopenReport explicitly passes isReopen: true, which directs NextStepUtils.ts:171-180 to evaluate WAITING_TO_SUBMIT:
What changes do you think we should make in order to solve the problem?
In src/libs/actions/IOU/ReportWorkflow.ts:
In retractReport, pass isReopen: true (or expand the property to isReopenOrRetract) into buildOptimisticNextStep:
In src/libs/NextStepUtils.ts:
Update type definitions and jsdoc if desired to clarify that isReopen covers both reopened and retracted report lifecycles.
This eliminates the optimistic flash at the source, ensuring seamless visual consistency from the exact moment the user confirms retraction.
What alternative solutions did you explore? (Optional)
Attempting to force retracted reports into auto-submit on the frontend alone. This was rejected because the backend contract for RetractReport explicitly emits WAITING_TO_SUBMIT, and frontend-only overrides would continuously conflict with incoming server state.
Automated Tests
In tests/actions/IOUTest/ReportWorkflowTest.ts:
Add a test for retractReport asserting that the generated optimistic nextStep matches CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT on a scheduled submit policy report, with zero UI flash.
Please re-state the problem that we are trying to solve in this issue.
In a workspace with Scheduled Submit (twice a month), manually submitting a report and then retracting it back to Open flashes the correct "Waiting for your expenses to automatically submit on the 1st and 16th of each month" next-step text briefly, then overwrites it with "Waiting for you to submit expenses" plus a manual Submit GBR in the LHN.
What is the root cause of that problem?
The flash is a genuine App bug: retractReport calls buildOptimisticNextStep without isReopen: true (ReportWorkflow.ts ~L708-718), while reopenReport passes it (~L544-555). Without the flag it falls into the harvesting branch and shows the auto-submit text optimistically; the server's RetractReport response then overwrites it with WAITING_TO_SUBMIT.
The final GBR comes from shouldCurrentUserSubmitReport returning true for any report the user owns that was retracted or reopened regardless of policy.harvesting (ReportUtils.ts ~L3670-3674) - a deliberate rule added in PR #66140 / #79893, not a recent regression.
What changes do you think we should make in order to solve the problem?
App-side fix for the flash: pass isReopen: true to buildOptimisticNextStep in retractReport, the same way reopenReport does. This removes the optimistic flash; nothing changes after the server response.
The final-state question (GBR + "waiting for you to submit") is a product decision: if retracted reports must return to Scheduled Submit, the backend RetractReport next step has to change first, and then the retracted/reopened override in shouldCurrentUserSubmitReport and ReportSecondaryActionUtils should only apply when harvesting is off.
What will I verify?
Retract a report in a Scheduled Submit workspace: no auto-submit text flash before the server response.
Unit test on retractReport asserting the optimistic nextStep.
Please re-state the problem that we are trying to solve in this issue.
In a workspace configured with Scheduled Submit (e.g., twice a month), when a user submits an expense report and then retracts it back to Open, the UI briefly flashes the scheduled auto-submit banner ("Waiting for your expenses to automatically submit on the 1st and 16th of each month") before immediately snapping to "Waiting for you to submit expenses" and rendering the green "Submit" button (GBR).
What is the root cause of that problem?
This is caused by a missing isReopen: true flag in the optimistic next-step builder for retracted reports, creating a mismatch between client optimistic state and the server response contract:
The Optimistic Flash in retractReport (src/libs/actions/IOU/ReportWorkflow.ts:708-718):
When retractReport executes, it builds the optimistic next step:
Notice that retractReport completely omits isReopen: true.
In NextStepUtils.ts:171-180, without isReopen: true, buildOptimisticNextStep treats the report as a brand-new open expense report and falls through into the harvesting/scheduled-submit calculation branch, optimistically rendering the auto-submit schedule banner.
The Contrast with reopenReport (ReportWorkflow.ts:544-555):
In reopenReport, isReopen: true is explicitly supplied:
Backend Contract and GBR Design:
Per PR Fix submit button color for reopened or retracted report #66140 and PR fix: add report owner check when computing outstanding state of chat … #79893, both retracted and reopened reports intentionally pause automatic harvesting so that the submitter can review their adjustments and manually submit. The server-side RetractReport command explicitly emits nextStep: WAITING_TO_SUBMIT, and shouldCurrentUserSubmitReport (src/libs/ReportUtils.ts:3670-3674) returns true whenever hasReportBeenRetracted(report) || isReportReopened(report).
Because retractReport optimistically showed the scheduled auto-submit text, when the server response arrives a moment later with WAITING_TO_SUBMIT, it causes a jarring UI flash and shifts the banner.
What changes do you think we should make in order to solve the problem?
Pass isReopen: true in retractReport (src/libs/actions/IOU/ReportWorkflow.ts:716):
Align retractReport with reopenReport by passing isReopen: true to buildOptimisticNextStep:
This guarantees that the optimistic update immediately outputs CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT, matching the server response from the exact moment the user clicks Retract and completely eliminating the UI flash.
What alternative solutions did you explore? (Optional)
Modifying shouldCurrentUserSubmitReport to suppress GBR on scheduled submit workspaces: Rejected because retracted reports intentionally require manual re-submission by design (allowing users to edit/add expenses without premature auto-harvesting).
Automated Tests
In tests/actions/IOUTest/ReportWorkflowTest.ts:
Add a unit test for retractReport asserting that on a workspace with scheduled submit (autoReportingFrequency: TWICE_A_MONTH), the returned optimistic nextStep.messageKey equals CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT and does not flash the harvesting schedule.
@Ollyws I reproduced this issue and tested the applied fix from Melvin’s proposal. While Melvin's 1-line change removes the visual flash, it does not actually fix the core bug reported in this issue. Here is why:
The Issue vs. Melvin’s Solution
What this issue expects: Retracting a report should restore the Scheduled Submit policy—the report should display the auto-submit schedule ("Waiting for your expenses to automatically submit on the 1st and 16th...") and show no green "Submit" button.
What Melvin's proposal actually does: It only hides the visual UI flash by forcing the report into a manual submission workflow ("Waiting for you to submit expenses" + green "Submit" button). It does not restore Scheduled Submit.
The Technical Reality (Network Verified)
We inspected the live network response during retraction. The backend RetractReport command explicitly returns nextStep: "waitingToSubmit" and pauses auto-harvesting.
Screencast.From.2026-10-20.11-27-33.webm
Because of this:
Frontend-only fixes cannot restore Scheduled Submit: Any frontend-only attempt to restore auto-submit will immediately be overwritten by the server response.
True fix requires Backend (BE): To actually achieve the issue's expected result, the backend team must update RetractReport to restore harvesting rather than requiring manual resubmission.
Demos
Reproduction Video:
Reprodemo104361.webm
**Melvin's Fix Video **
melvinFix104361.webm
Would you like us to submit a full formal proposal outlining both decision paths (Backend requirement to restore auto-submit vs. FE-only flash mitigation), or would you prefer to escalate this to an internal engineer first for backend confirmation?
Please re-state the problem that we are trying to solve in this issue.
In a workspace configured with Scheduled Submit (e.g. twice a month), when a user retracts a previously submitted expense report back to Open, the UI optimistically flashes the scheduled auto-submit text ("Waiting for your expenses to automatically submit on the 1st and 16th of each month") before the server response settles on "Waiting for you to submit expenses" and renders the green "Submit" button (GBR).
What is the root cause of that problem?
A divergence between the optimistic NextStep builder and the server contract:
Frontend Optimistic Divergence (src/libs/actions/IOU/ReportWorkflow.ts:retractReport): retractReport calls buildOptimisticNextStep with predictedNextStatus: CONST.REPORT.STATUS_NUM.OPEN, but does not pass an explicit intent flag indicating this is a retracted report. In src/libs/NextStepUtils.ts, the case CONST.REPORT.STATUS_NUM.OPEN evaluates if (policy?.harvesting?.enabled && hasTransactions), resolving to WAITING_FOR_AUTOMATIC_SUBMIT.
Server Contract Intent (RetractReport API):
When an expense report is explicitly retracted by the submitter, the backend halts automatic harvesting on that report to avoid immediately re-submitting expenses that the user intentionally pulled back to edit/adjust, returning nextStep: "waitingToSubmit".
Because the optimistic update assumes automated harvesting while the server enforces manual resubmission, a visual flash / layout shift occurs upon receiving the server response.
What changes do you think we should make in order to solve the problem?
This guarantees 100% synchronization between frontend optimistic state and server payload, eliminating the UI flash completely without regressions.
Alternative / Product Escalation Path:
If Expensify Product determines that retracted reports should resume automatic harvesting on future scheduled cycles without manual user intervention, that change requires a backend update to the RetractReport command contract. In that event, the frontend can easily omit isRetracted once the BE change lands. Until such a product shift is confirmed, aligning the optimistic state with the current server contract is the correct, regression-free implementation.
What alternative solutions did you explore? (Optional)
Setting isReopen: true directly in retractReport (proposed by MelvinBot): while functionally similar, semantically conflates report reopen (unapproving/rejecting by manager) with submitter retraction. Introducing an explicit isRetracted property preserves clean domain separation and avoids unintended side effects in downstream analytics/guards.
The question here is whether we restore scheduled submit after the report is retracted, if not Melvin's proposal looks good, otherwise this will require some backend work.
Activity
applause-bot commentedon Oct 19, 2026
While Applause doesn't embed attachments for this bug, here are the links for quick view:
https://platform.applause.com/services/links/v1/external/2f2c0998e5bb6555689b51a86ffc209535b932939369ca49de0555be351743aa
https://platform.applause.com/services/links/v1/external/e96171635e8b5882132ce5ae2b9bf35720f332a80b4bcd2ab545f54fb818a508
MelvinBot commentedon Oct 19, 2026
Proposal
Summary: The final state ("Waiting for you to submit expenses" plus a Submit GBR) matches how the App and the server treat retracted reports today. The real App bug is the short flash of the auto-submit text. That flash comes from
retractReportbuilding the wrong optimistic next step.What is the root cause of that problem?
retractReportcallsbuildOptimisticNextStepwithoutisReopen: true(ReportWorkflow.ts:708-718). Because of that, it falls into the harvesting branch and shows "automatically submit on the 1st and 16th".reopenReportdoes passisReopen: true(ReportWorkflow.ts:544-555), which givesWAITING_TO_SUBMIT(NextStepUtils.ts:171-180).report.nextStep. TheRetractReportresponse replaces the optimistic value withWAITING_TO_SUBMIT.shouldCurrentUserSubmitReportreturns true for any report the user owns that was retracted or reopened, whateverpolicy.harvestingis set to (ReportUtils.ts:3670-3674). The Submit button logic follows the same rule (ReportSecondaryActionUtils.ts:288-297). This rule was added on purpose in Fix submit button color for reopened or retracted report and fix: add report owner check when computing outstanding state of chat …. It is not a recent regression.What changes do you think we should make in order to solve the problem?
This depends on a product decision. An internal engineer needs to confirm whether backend Scheduled Submit picks up retracted reports.
isReopen: truetobuildOptimisticNextStepinretractReport, the same wayreopenReportdoes. This removes the flash. Add aretractReportunit test that checks the optimisticnextStep. The GBR and final text then stay as they are, by design.RetractReportnext step and include retracted reports in harvesting. That change is outside the App repo, so escalate it to an internal engineer. After that, the App should apply the retracted/reopened override inshouldCurrentUserSubmitReportandReportSecondaryActionUtilsonly when harvesting is off. An App-only change would conflict with the server's next step.Investigation details
hasReportBeenRetractedchecks the report field first, then anyRETRACTEDreport action. Once set, the flag stays for the life of the report (ReportUtils.ts:14575-14601).retractReportsuccessData only clears pending fields and never writesnextStep. The overwrite therefore comes from the server's update.retractReporttests intests/actions/IOUTest/ReportWorkflowTest.tsdon't checknextStep.Next Steps for Contributor+ team:
To accept:
@MelvinBot implement [this](https://github.com/Expensify/App/issues/104361)to create a draft PR.To refine:
@MelvinBot <your feedback>To reject: Explain why you are rejecting Melvin's proposal.
view run
melvin-bot commentedon Oct 19, 2026
Triggered auto assignment to Contributor-plus team member for initial proposal review - @Ollyws (
External)[-]Scheduled Submit - Retracting a report fails restore the workspace Scheduled Submit policy[/-][+][$175] Scheduled Submit - Retracting a report fails restore the workspace Scheduled Submit policy[/+]melvin-bot commentedon Oct 19, 2026
Job added to Upwork: https://www.upwork.com/jobs/~022112193818585048068
camesenin commentedon Oct 19, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When retracting an expense report in a workspace configured with Scheduled Submit, an optimistic UI flash briefly displays auto-submit text before snapping to "Waiting for you to submit expenses" and rendering the green "Submit" button (GBR).
What is the root cause of that problem?
A mismatch between the optimistic NextStep builder and the server contract:
src/libs/actions/IOU/ReportWorkflow.ts:708-718,retractReportcallsbuildOptimisticNextStep:retractReportomitsisReopen: true. Without this flag,buildOptimisticNextSteptreats the open report as a standard auto-submitting draft and falls into the harvesting branch, optimistically flashing the scheduled auto-submit banner.reopenReport: InReportWorkflow.ts:544-555,reopenReportexplicitly passesisReopen: true, which directsNextStepUtils.ts:171-180to evaluateWAITING_TO_SUBMIT:WAITING_TO_SUBMIT. Because the optimistic step inretractReportgenerated the auto-submit message, the client experiences a jarring UI flash when the server response arrives and replaces it withWAITING_TO_SUBMIT.What changes do you think we should make in order to solve the problem?
src/libs/actions/IOU/ReportWorkflow.ts:In
retractReport, passisReopen: true(or expand the property toisReopenOrRetract) intobuildOptimisticNextStep:src/libs/NextStepUtils.ts:Update type definitions and jsdoc if desired to clarify that
isReopencovers both reopened and retracted report lifecycles.This eliminates the optimistic flash at the source, ensuring seamless visual consistency from the exact moment the user confirms retraction.
What alternative solutions did you explore? (Optional)
Attempting to force retracted reports into auto-submit on the frontend alone. This was rejected because the backend contract for
RetractReportexplicitly emitsWAITING_TO_SUBMIT, and frontend-only overrides would continuously conflict with incoming server state.Automated Tests
In
tests/actions/IOUTest/ReportWorkflowTest.ts:retractReportasserting that the generated optimisticnextStepmatchesCONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMITon a scheduled submit policy report, with zero UI flash.Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~0170d6b02e9440e604
melvin-bot commentedon Oct 19, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
khizzcr7 commentedon Oct 19, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
In a workspace with Scheduled Submit (twice a month), manually submitting a report and then retracting it back to Open flashes the correct "Waiting for your expenses to automatically submit on the 1st and 16th of each month" next-step text briefly, then overwrites it with "Waiting for you to submit expenses" plus a manual Submit GBR in the LHN.
What is the root cause of that problem?
The flash is a genuine App bug:
retractReportcallsbuildOptimisticNextStepwithoutisReopen: true(ReportWorkflow.ts~L708-718), whilereopenReportpasses it (~L544-555). Without the flag it falls into the harvesting branch and shows the auto-submit text optimistically; the server'sRetractReportresponse then overwrites it withWAITING_TO_SUBMIT.The final GBR comes from
shouldCurrentUserSubmitReportreturning true for any report the user owns that was retracted or reopened regardless ofpolicy.harvesting(ReportUtils.ts~L3670-3674) - a deliberate rule added in PR #66140 / #79893, not a recent regression.What changes do you think we should make in order to solve the problem?
isReopen: truetobuildOptimisticNextStepinretractReport, the same wayreopenReportdoes. This removes the optimistic flash; nothing changes after the server response.RetractReportnext step has to change first, and then the retracted/reopened override inshouldCurrentUserSubmitReportandReportSecondaryActionUtilsshould only apply when harvesting is off.What will I verify?
retractReportasserting the optimistic nextStep.sijo0218 commentedon Oct 20, 2026
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~011091133bbb09cd1c
Proposal
Please re-state the problem that we are trying to solve in this issue.
In a workspace configured with Scheduled Submit (e.g., twice a month), when a user submits an expense report and then retracts it back to Open, the UI briefly flashes the scheduled auto-submit banner ("Waiting for your expenses to automatically submit on the 1st and 16th of each month") before immediately snapping to "Waiting for you to submit expenses" and rendering the green "Submit" button (GBR).
What is the root cause of that problem?
This is caused by a missing
isReopen: trueflag in the optimistic next-step builder for retracted reports, creating a mismatch between client optimistic state and the server response contract:The Optimistic Flash in
retractReport(src/libs/actions/IOU/ReportWorkflow.ts:708-718):When
retractReportexecutes, it builds the optimistic next step:Notice that
retractReportcompletely omitsisReopen: true.In
NextStepUtils.ts:171-180, withoutisReopen: true,buildOptimisticNextSteptreats the report as a brand-new open expense report and falls through into the harvesting/scheduled-submit calculation branch, optimistically rendering the auto-submit schedule banner.The Contrast with
reopenReport(ReportWorkflow.ts:544-555):In
reopenReport,isReopen: trueis explicitly supplied:In
NextStepUtils.ts:171-180, whenisReopenis true, the next step immediately assigns:Backend Contract and GBR Design:
Per PR Fix submit button color for reopened or retracted report #66140 and PR fix: add report owner check when computing outstanding state of chat … #79893, both retracted and reopened reports intentionally pause automatic harvesting so that the submitter can review their adjustments and manually submit. The server-side
RetractReportcommand explicitly emitsnextStep: WAITING_TO_SUBMIT, andshouldCurrentUserSubmitReport(src/libs/ReportUtils.ts:3670-3674) returnstruewheneverhasReportBeenRetracted(report) || isReportReopened(report).Because
retractReportoptimistically showed the scheduled auto-submit text, when the server response arrives a moment later withWAITING_TO_SUBMIT, it causes a jarring UI flash and shifts the banner.What changes do you think we should make in order to solve the problem?
Pass
isReopen: trueinretractReport(src/libs/actions/IOU/ReportWorkflow.ts:716):Align
retractReportwithreopenReportby passingisReopen: truetobuildOptimisticNextStep:This guarantees that the optimistic update immediately outputs
CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT, matching the server response from the exact moment the user clicks Retract and completely eliminating the UI flash.What alternative solutions did you explore? (Optional)
shouldCurrentUserSubmitReportto suppress GBR on scheduled submit workspaces: Rejected because retracted reports intentionally require manual re-submission by design (allowing users to edit/add expenses without premature auto-harvesting).Automated Tests
In
tests/actions/IOUTest/ReportWorkflowTest.ts:retractReportasserting that on a workspace with scheduled submit (autoReportingFrequency: TWICE_A_MONTH), the returned optimisticnextStep.messageKeyequalsCONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMITand does not flash the harvesting schedule.melvin-bot commentedon Oct 20, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
emkhalid commentedon Oct 20, 2026
@Ollyws I reproduced this issue and tested the applied fix from Melvin’s proposal. While Melvin's 1-line change removes the visual flash, it does not actually fix the core bug reported in this issue. Here is why:
The Issue vs. Melvin’s Solution
The Technical Reality (Network Verified)
We inspected the live network response during retraction. The backend
RetractReportcommand explicitly returnsnextStep: "waitingToSubmit"and pauses auto-harvesting.Screencast.From.2026-10-20.11-27-33.webm
Because of this:
RetractReportto restore harvesting rather than requiring manual resubmission.Demos
Reprodemo104361.webm
melvinFix104361.webm
Would you like us to submit a full formal proposal outlining both decision paths (Backend requirement to restore auto-submit vs. FE-only flash mitigation), or would you prefer to escalate this to an internal engineer first for backend confirmation?
dhaulagani commentedon Oct 20, 2026
Contributor details
Your Expensify account email: [email protected]
Upwork Profile Link: https://www.upwork.com/freelancers/~017b76638cdbe0f8d6
Proposal
Please re-state the problem that we are trying to solve in this issue.
In a workspace configured with Scheduled Submit (e.g. twice a month), when a user retracts a previously submitted expense report back to Open, the UI optimistically flashes the scheduled auto-submit text ("Waiting for your expenses to automatically submit on the 1st and 16th of each month") before the server response settles on "Waiting for you to submit expenses" and renders the green "Submit" button (GBR).
What is the root cause of that problem?
A divergence between the optimistic
NextStepbuilder and the server contract:Frontend Optimistic Divergence (
src/libs/actions/IOU/ReportWorkflow.ts:retractReport):retractReportcallsbuildOptimisticNextStepwithpredictedNextStatus: CONST.REPORT.STATUS_NUM.OPEN, but does not pass an explicit intent flag indicating this is a retracted report. Insrc/libs/NextStepUtils.ts, thecase CONST.REPORT.STATUS_NUM.OPENevaluatesif (policy?.harvesting?.enabled && hasTransactions), resolving toWAITING_FOR_AUTOMATIC_SUBMIT.Server Contract Intent (
RetractReportAPI):When an expense report is explicitly retracted by the submitter, the backend halts automatic harvesting on that report to avoid immediately re-submitting expenses that the user intentionally pulled back to edit/adjust, returning
nextStep: "waitingToSubmit".Because the optimistic update assumes automated harvesting while the server enforces manual resubmission, a visual flash / layout shift occurs upon receiving the server response.
What changes do you think we should make in order to solve the problem?
Primary Architecture Solution (Contract Alignment & Flash Elimination):
src/libs/actions/IOU/ReportWorkflow.ts, passisRetracted: trueintobuildOptimisticNextStepparameters insideretractReport:src/libs/NextStepUtils.ts, addisRetractedtoBuildNextStepNewParamsand handle it incase CONST.REPORT.STATUS_NUM.OPEN:This guarantees 100% synchronization between frontend optimistic state and server payload, eliminating the UI flash completely without regressions.
Alternative / Product Escalation Path:
If Expensify Product determines that retracted reports should resume automatic harvesting on future scheduled cycles without manual user intervention, that change requires a backend update to the
RetractReportcommand contract. In that event, the frontend can easily omitisRetractedonce the BE change lands. Until such a product shift is confirmed, aligning the optimistic state with the current server contract is the correct, regression-free implementation.What alternative solutions did you explore? (Optional)
isReopen: truedirectly inretractReport(proposed by MelvinBot): while functionally similar, semantically conflates report reopen (unapproving/rejecting by manager) with submitter retraction. Introducing an explicitisRetractedproperty preserves clean domain separation and avoids unintended side effects in downstream analytics/guards.melvin-bot commentedon Oct 20, 2026
✅ Contributor details stored successfully. Thank you for contributing to Expensify!
Ollyws commentedon Oct 20, 2026
The question here is whether we restore scheduled submit after the report is retracted, if not Melvin's proposal looks good, otherwise this will require some backend work.
🎀👀🎀 C+ reviewed
melvin-bot commentedon Oct 20, 2026
Triggered auto assignment to @MonilBhavsar, see https://stackoverflow.com/c/expensify/questions/7972 for more details.