Skip to content

[Due for payment 2026-10-01] Web - Report - Chat is not autoscrolled to the bottom after sending messages #99559

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.4.61-1
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from TestRail: https://github.com/Expensify/Expensify/issues/440269
Email or phone of affected tester (no customers): N/A
Issue reported by: Applause Internal Team

Action Performed:

Prerequisite: Account has at least one workspace.

  1. Open the staging.new.expensify.com website.
  2. Open any workspace chat.
  3. Submit expense to workspace
  4. Go to expense detail has create from step 1
  5. Send multiple messages to trigger a scroll
  6. Scroll up and edit category or description
  7. Send another message after edit catetory
  8. Try to send another message
  9. Note that report is not autoscrolled to the bottom.

Expected Result:

Report should be autoscrolled to the bottom after sending messages.

Actual Result:

Report is not autoscrolled to the bottom after making editions and sending messages.

Workaround:

N/A

Platforms:

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

Screenshots/Videos

Bug7236768_1787096211948.Scr.mp4
Upwork Automation - Do Not Edit
Issue OwnerCurrent Issue Owner: @mallenexpensify

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Aug 26, 2026
  2. MelvinBot commented on Aug 26, 2026

    @MelvinBot
    Contributor

    Proposal

    ℹ️ Confidence: Medium — root cause is pinned to a concrete, statically-provable code mechanism, but I couldn't get a live web repro to confirm the final micro-step (the test session hit an environment/infra issue). The behavior is already confirmed reproducible in staging & production by Applause.

    What is the root cause of that problem?

    The expense-report view (MoneyRequestReportActionsList) has its own autoscroll logic — it does not use the shared inverted-chat live-tail hook. Its "should I autoscroll on a new message?" decision hinges on a single flag, hasNewestReportAction, computed as:

    hasNewestReportAction = lastAction?.created === getReportLastVisibleActionCreated(report, transactionThreadReport)
    

    (MoneyRequestReportActionsList.tsx:228-229)

    When you inline-edit a transaction's category/description, an optimistic MODIFIED_EXPENSE action is written into the transaction thread. That write advances the newest-action timestamp on one side of that equality but not the other (the optimistic edit updates lastReadTime but does not bump lastVisibleActionCreated, UpdateMoneyRequest.ts:1838-1870), so the equality breaks and hasNewestReportAction flips to false.

    With that flag stuck false, the position-based autoscroll hook refuses to fire on your next message because of its hasNewestReportAction && prevHasNewestReportAction guard (useScrollToEndOnNewMessageReceived.ts:65-82). Because this list is not inverted, nothing else pins it to the bottom, so the report stays where you left it — exactly the reported symptom. Sending a message without first editing works because hasNewestReportAction is still true.

    Investigation details & evidence
    • Two autoscroll paths exist in this view:
    • getReportLastVisibleActionCreated returns max(report, transactionThread) last-visible timestamps (ReportUtils.ts:13211-13215), so a stale/desynced timestamp on either side breaks the hasNewestReportAction equality.
    • The flip is cleanest for one-transaction expense reports (where transactionThreadReport is populated), which matches the repro steps (submit one expense → open its detail).
    • Secondary contributor: the scroll-offset used by Path B (scrollOffsetRef / scrollingVerticalBottomOffset) is only updated inside the scroll handler onTrackScrolling. An inline edit changes content height (popover/inline cell open/close + the appended row) without necessarily emitting a scroll event, so the offset can also go stale and independently suppress Path B.
    • Ruled out: inline category/description editing is a popover / in-cell interaction, not an RHP push/pop, so "returning from a modal resets scroll" does not apply — the list stays mounted.

    Open question needing a live repro to confirm: whether the failure is purely Path B being gated off by prevHasNewestReportAction=false, or whether Path A's scrollToIndex also fails to land because FlashList maintainVisibleContentPosition re-anchors the viewport after the edit changed content above (MoneyRequestReportUnifiedList.tsx:346).

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

    Make the autoscroll decision robust to an inline edit desyncing hasNewestReportAction:

    1. Preferred: when the current user sends a message, always scroll to the bottom regardless of hasNewestReportAction (i.e. rely on the unconditional Path A / scrollToBottomForCurrentUserAction and confirm it actually lands after an edit). Sending your own message is an unambiguous intent to jump to the bottom.
    2. And/or stop letting an inline MODIFIED_EXPENSE edit flip hasNewestReportAction — either exclude MODIFIED_EXPENSE actions from the lastAction/lastVisibleActionCreated comparison at MoneyRequestReportActionsList.tsx:228-229, or ensure the optimistic edit keeps both timestamps consistent so the flag stays accurate.

    What alternative solutions did you explore? (Optional)

    Refresh scrollOffsetRef after inline-edit-driven layout changes (so the 250px near-bottom gate in Path B isn't evaluated against a stale offset). This addresses the secondary contributor but not the primary hasNewestReportAction flip, so it's a partial fix at best.


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


    view run

  3. added
    ExternalAdded to denote the issue can be worked on by a contributor
    on Aug 26, 2026
  4. melvin-bot commented on Aug 26, 2026

    @melvin-bot

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

  5. mukhrr commented on Aug 26, 2026

    @mukhrr
    Contributor
    • Preferred: when the current user sends a message, always scroll to the bottom regardless of hasNewestReportAction (i.e. rely on the unconditional Path A / scrollToBottomForCurrentUserAction and confirm it actually lands after an edit). Sending your own message is an unambiguous intent to jump to the bottom.
    • And/or stop letting an inline MODIFIED_EXPENSE edit flip hasNewestReportAction — either exclude MODIFIED_EXPENSE actions from the lastAction/lastVisibleActionCreated comparison at MoneyRequestReportActionsList.tsx:228-229, or ensure the optimistic edit keeps both timestamps consistent so the flag stays accurate.

    I don't think this can fix the issue @Pujan92

  6. Javokhiir commented on Aug 26, 2026

    @Javokhiir

    @Pujan92 i looked a bit deeper. i don't think hasNewestReportAction can be the main RCA here. when current user sends a message, MoneyRequestReportActionsList already uses scrollToBottomForCurrentUserAction -> scrollToBottom(), which doesn't check that flag.

    so Melvin's preferred fix is basically what the code already does. i think the failure is in this scroll path after expense edit, not in timestamp guard. what do you think?

  7. Uzaifm127 commented on Aug 31, 2026

    @Uzaifm127
  8. melvin-bot commented on Aug 31, 2026

    @melvin-bot

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

  9. Pujan92 commented on Sep 1, 2026

    @Pujan92
    Contributor

    I will review max by tomorrow

  10. removed
    ExternalAdded to denote the issue can be worked on by a contributor
    on Sep 3, 2026
  11. 66 remaining items

  12. melvin-bot commented on Sep 30, 2026

    @melvin-bot

    Payment Summary

    Resolving PRs:

    Upwork Job

    • Reviewer: @mananjadhav owed $175 via NewDot
    • Assignee: @Uzaifm127 requires payment (Needs manual offer from BZ)

    BugZero Checklist (@mallenexpensify)

    • I have confirmed assignees, roles, and Upwork contracts look correct
    • I have paid out Upwork contracts / manual NewDot requests
    • [BugZero Assignee] I have created a GH issue for creating/updating the regression test once above steps have been agreed upon
  13. Uzaifm127 commented on Oct 1, 2026

    @Uzaifm127
    Contributor

    @mallenexpensify The payment due here is $250 as this issue was worked before we announced $175 and this issue was Help wanted. TY!

    @mananjadhav Could you please provide the checklist here? Thanks

  14. Uzaifm127 commented on Oct 2, 2026

    @Uzaifm127
    Contributor

    @mallenexpensify Friendly bump here for payment processing. TY!

  15. mallenexpensify commented on Oct 3, 2026

    @mallenexpensify
    Contributor

    Payment Summary

    Contributor: @Uzaifm127 paid $250 via Upwork
    Contributor+: @mananjadhav due $250 via NewDot

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

    @mananjadhav plz complete the Contributor+ checklist and tag me in a post once you have. Thx

  16. Uzaifm127 commented on Oct 3, 2026

    @Uzaifm127
    Contributor

    @mallenexpensify Accepted the offer, Thank you.

  17. mallenexpensify commented on Oct 3, 2026

    @mallenexpensify
    Contributor

    @Uzaifm127 paid, summary updated above. Thx.

    @mananjadhav plz complete the Contributor+ checklist and tag me in a post once you have. Thx

  18. mananjadhav commented on Oct 5, 2026

    @mananjadhav
    Collaborator

    Contributor+ Checklist:

    • [Contributor] The offending PR and associated issue have been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.

      Link to the comment on the PR: No specific PR. We had an outdated external dependency.
      Link to the comment on the Issue:

    • [Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.

      Link to discussion: NA

    • [Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.

    This is already covered in the existing regression test. We don't need a new one.

  19. mananjadhav commented on Oct 5, 2026

    @mananjadhav
    Collaborator

    @mallenexpensify The checklist is updated.

  20. garrettmknight commented on Oct 19, 2026

    @garrettmknight
    Contributor

    $250 approved for @mananjadhav

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

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions