Skip to content

[Due for payment 2026-03-30] Task - Assignee avatar is inconsistent in task & assignee page #85532

Closed

Description

@jponikarchuk

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.3.39-0
Reproducible in staging?: Yes
Reproducible in production?: No
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #85032
Email or phone of affected tester (no customers): dreamnitethedragon+yydyd373@gmail.com
Issue reported by: Applause Internal Team
Bug source: Exploratory - Significant User Experience Deterioration
Device used: Redminote 10S Android 13
App Component: Other

Action Performed:

  1. Launch app
  2. Open self dm
  3. Create a task entering existing user as assignee
  4. Open the task
  5. Open the assignee

Expected Result:

Assignee avatar must be consistent in task & assignee page.

Actual Result:

Assignee avatar is inconsistent in task & assignee page.

Workaround:

Unknown

Platforms:

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

Screenshots/Videos

Video.mp4

View all open jobs on GitHub

Issue OwnerCurrent Issue Owner: @dukenv0307

Activity

  1. added
    DeployBlockerCashThis issue or pull request should block deployment
    BugSomething is broken. Auto assigns a BugZero manager.
    on Mar 17, 2026
  2. melvin-bot commented on Mar 17, 2026

    @melvin-bot

    You have been assigned to this deploy blocker because you recently merged this PR: #85032

  3. melvin-bot commented on Mar 17, 2026

    @melvin-bot

    💬 A slack conversation has been started in #expensify-open-source

  4. github-actions commented on Mar 17, 2026

    @github-actions
    Contributor

    👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

    1. Identify the pull request that introduced this issue and revert it.
    2. Find someone who can quickly fix the issue.
    3. Fix the issue yourself.
  5. OSBotify commented on Mar 17, 2026

    @OSBotify
    Contributor

    🔍 Investigation Summary

    Classification: Frontend bug
    Causing PR: #85032 - "fix: Assigned task appears hidden and assignee status not shown" by @nkdengineer (High confidence)
    Related Issues: #81714 (original issue that #85032 was fixing)

    Recommendation: ROLL FORWARD

    While PR #85032 can be cleanly reverted, rolling forward with a fix is the better approach because:

    1. Reverting would reintroduce bug [$250] Task - Assigned task appears hidden and assignee status not shown #81714 (tasks assigned to new users appear "Hidden")
    2. The fix is straightforward - the isOptimisticPersonalDetail flag is being set incorrectly for existing users
    3. The root cause is well-understood and isolated to the logic in TaskAssigneeSelectorModal.tsx

    Labels: Keeping DeployBlockerCash (App PR caused the issue, App deploy remains blocked)

    📋 Detailed Analysis

    Evidence

    PR #85032 modified how optimistic personal details are handled when assigning tasks. The PR introduced tracking via the isOptimisticPersonalDetail flag to conditionally clear optimistic personal details on API success.

    Key changes in PR #85032:

    1. Added isOptimisticPersonalDetail flag to personal details
    2. Changed TaskAssigneeSelectorModal.tsx line 155: isOptimisticPersonalDetail: !allPersonalDetails?.[option?.accountID ?? CONST.DEFAULT_NUMBER_ID]
    3. Made clearing of personal details conditional in ReportUtils.ts (only clears if isOptimisticPersonalDetail(assigneeAccountID) returns true)

    Verification

    Root Cause

    The bug occurs in TaskAssigneeSelectorModal.tsx at line 155:

    isOptimisticPersonalDetail: !allPersonalDetails?.[option?.accountID ?? CONST.DEFAULT_NUMBER_ID]

    Problem: This logic incorrectly marks existing users as optimistic when their personal details simply haven't been loaded into the local allPersonalDetails object yet.

    Flow of the bug:

    1. User selects an existing user (who they haven't chatted with before) as task assignee
    2. allPersonalDetails[accountID] is undefined/empty (not yet loaded)
    3. Code sets isOptimisticPersonalDetail: true (incorrectly)
    4. API call succeeds and returns real personal details
    5. Success handler checks isOptimisticPersonalDetail(assigneeAccountID) which returns true
    6. Personal details get cleared: {[assigneeAccountID]: null}
    7. Avatar becomes inconsistent - task page shows one avatar, assignee page shows fallback/default avatar

    Why this breaks:

    Recommended fix approach:
    The fix should ensure that isOptimisticPersonalDetail is only set to true for genuinely new/optimistic users, not for existing users whose personal details happen to be unloaded. This might require checking additional signals (e.g., whether the user exists in the backend) or preserving the personal details differently.

  6. MelvinBot commented on Mar 17, 2026

    @MelvinBot
    Contributor

    Proposal

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

    When creating a task and assigning it to an existing user, the assignee's avatar is inconsistent between the task detail view and the assignee's page. This regression was introduced in staging by PR #85032.

    What is the root cause of that problem?

    PR #85032 changed getTaskAssigneeChatOnyxData in src/libs/ReportUtils.ts to only null out the assignee's personal details on API success for optimistic (new) users. For existing users, the null-out is now skipped.

    The problem lies in setNewOptimisticAssignee (src/libs/actions/Task.ts:878-885). When called for an existing user (who has no 1:1 DM chat with the current user), it merges a partial personal details object (only 5 fields: accountID, avatar, displayName, login, isOptimisticPersonalDetail) into ONYXKEYS.PERSONAL_DETAILS_LIST via Onyx.merge.

    Before PR #85032:

    1. setNewOptimisticAssignee merges partial personal details
    2. On API success, the success callback nulls the entire entry ({[assigneeAccountID]: null})
    3. The backend response then writes fresh, complete personal details
    4. Both the task view and assignee page show the correct, server-provided avatar

    After PR #85032:

    1. setNewOptimisticAssignee merges partial personal details (with isOptimisticPersonalDetail: false for existing users)
    2. On API success, the success callback skips the null (because isOptimisticPersonalDetail() returns false)
    3. The backend response merges on top, but the partial optimistic data persists
    4. The task view (via useReportActionAvatars at src/components/ReportActionAvatars/useReportActionAvatars.ts:128) reads personalDetails?.[id]?.avatar ?? FallbackAvatar
    5. The profile page (via openPublicProfilePage) fetches fresh data from the server, updating the avatar

    The inconsistency arises because the task view uses the locally-stored (potentially stale) avatar, while navigating to the assignee triggers a fresh server fetch that returns the canonical avatar.

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

    In setNewOptimisticAssignee (src/libs/actions/Task.ts:878-885), skip the Onyx.merge into PERSONAL_DETAILS_LIST when the user already exists (i.e., when isOptimisticPersonalDetail is false). The merge into personal details is only needed for truly new/optimistic users whose data doesn't exist in the store yet. For existing users, their personal details are already in PERSONAL_DETAILS_LIST and don't need to be overwritten with a partial object.

    Specifically, wrap the existing Onyx.merge call at line 885 with a condition:

    if (assigneePersonalDetails.isOptimisticPersonalDetail) {
        Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {[assigneePersonalDetails.accountID]: optimisticPersonalDetailsListAction});
    }
    

    This preserves the fix from PR #85032 (not nulling existing users on success) while preventing the partial overwrite that causes avatar inconsistency.

    What alternative solutions did you explore? (Optional)

    1. Revert the isOptimisticPersonalDetail condition in getTaskAssigneeChatOnyxData — This would re-introduce the original bug from issue [$250] Task - Assigned task appears hidden and assignee status not shown #81714 (task appearing hidden for existing users).

    2. Make the optimistic object include ALL personal details fields — This would mean copying the full personal details into the optimistic object. While it would prevent data loss, it adds complexity and the merge is still unnecessary for existing users.

    3. Keep the null-out but immediately re-merge the existing data — Overly complex and still has a brief flicker where data is null.


    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.

  7. dangrous commented on Mar 17, 2026

    @dangrous
    Contributor

    Can confirm, comes from #81714 PR. @nkdengineer I can't assign you here until you comment I guess? Not sure why I could for @dukenv0307

  8. nkdengineer commented on Mar 17, 2026

    @nkdengineer
    Contributor

    @dangrous I checked this for a while. Currently, the bug is visible after our PR, but the RCA is not our PR. On production, the assignee is not displayed in the assignee page after assigning the task.

    The RCA is

    1. We still have another wrong code here, which clears the assignee from participants unexpectedly, even if it's not an optimistic user. Which causes useReportAvatars hook to return the wrong avatar (it returns the current user avatar because the assignee doesn't appear in the participant list of the report)

    App/src/libs/ReportUtils.ts

    Lines 10385 to 10398 in a57e04d

    successData.push(
    {
    onyxMethod: Onyx.METHOD.MERGE,
    key: `${ONYXKEYS.COLLECTION.REPORT}${assigneeChatReportID}`,
    value: {
    pendingFields: {
    createChat: null,
    },
    // BE will send a different participant. We clear the optimistic one to avoid duplicated entries
    participants: {[assigneeAccountID]: null},
    },
    },
    {
    onyxMethod: Onyx.METHOD.MERGE,

    1. Also found the backend problem. CreateTask report API doesn't create the chat report with the assignee, even if the param exists. Then when we open the assignee chat report which is created in optimistic data, not found error appears
    Screen.Recording.2026-03-17.at.20.38.39.mov
    Image

    To fix this issue, we only need to fix point 1

  9. 7 remaining items

  10. dangrous commented on Mar 20, 2026

    @dangrous
    Contributor

    We're on staging!

  11. added
    Awaiting PaymentAuto-added when associated PR is deployed to production
    and removed on Mar 23, 2026
  12. changed the title [-]Task - Assignee avatar is inconsistent in task & assignee page[/-] [+][Due for payment 2026-03-30] Task - Assignee avatar is inconsistent in task & assignee page[/+] on Mar 23, 2026
  13. melvin-bot commented on Mar 23, 2026

    @melvin-bot

    Reviewing label has been removed, please complete the "BugZero Checklist".

  14. melvin-bot commented on Mar 23, 2026

    @melvin-bot

    The solution for this issue has been 🚀 deployed to production 🚀 in version 9.3.41-4 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

    If no regressions arise, payment will be issued on 2026-03-30. 🎊

    For reference, here are some details about the assignees on this issue:

    • @dukenv0307 requires payment through NewDot Manual Requests
  15. melvin-bot commented on Mar 23, 2026

    @melvin-bot

    @dukenv0307 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]

  16. melvin-bot commented on Mar 23, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

  17. dukenv0307 commented on Mar 24, 2026

    @dukenv0307
    Contributor

    No need for payment

  18. dangrous commented on Mar 24, 2026

    @dangrous
    Contributor

    Love it! I will close this out, anyone can ping if that's in error.

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.EngineeringWeeklyKSv2

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions