Skip to content

[Due for payment 2026-03-30] Workspace settings - Photo is not updated on WS #85673

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.40-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: https://test-management.browserstack.com/projects/2219752/test-runs/TR-10400/folder/13177080/41237930/1260625268?status_id=1014144&issue_type=jira&folder_ids=13177080%2C31025987&p=2
Email or phone of affected tester (no customers): lattelover1412+1803e@gmail.com
Issue reported by: Applause Internal Team
Bug source: Regression TC Execution
Device used: Web
App Component: Workspace Settings

Action Performed:

Precondition: user has existing WS

  1. Open the link staging.new.expensify.com
  2. User logged in
  3. Navigate to Workspace settings
  4. Click on the Workspace avatar >> Upload an image >> Click "Save"

Expected Result:

Image should be uploaded

Actual Result:

Image is not updated when user attempt to upload as WS avatar

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

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Mar 18, 2026
  2. melvin-bot commented on Mar 18, 2026

    @melvin-bot

    Triggered auto assignment to @Julesssss (DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.

  3. melvin-bot commented on Mar 18, 2026

    @melvin-bot

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

  4. github-actions commented on Mar 18, 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 18, 2026

    @OSBotify
    Contributor

    Investigation Summary

    Classification: Frontend bug
    Causing PR: #85248 - "Bump onyx to 3.0.46" by @VickyStash (High confidence)
    Related Issues: #76628 (similar previous issue with avatar updates)

    Recommendation: REVERT

    The PR should be reverted to restore avatar upload functionality. A roll-forward fix would require investigating the interaction between the new synchronous Onyx subscriber behavior and the avatar upload flow.

    Labels: Removing DeployBlocker (no backend changes involved)

    Detailed Analysis

    Evidence

    PR #85248 bumped react-native-onyx from 3.0.45 to 3.0.46, which changed subscriber notifications to be more synchronous (removing macro/microtasks). This PR is in the staging deploy (v9.3.40-0) but not in production, matching the reproduction pattern (staging: yes, production: no).

    The PR description explicitly states:

    "This Onyx update changes subscriber notifications to be more synchronous, which exposed two issues in the App"

    While the PR fixed two known issues (side effect in withPolicy HOC and new expense scroll/highlight race condition), the more synchronous behavior likely exposed a new timing issue with workspace avatar uploads.

    Verification

    1. File affected: src/pages/workspace/WorkspaceOverviewPage.tsx uses AvatarWithImagePicker with onImageSelected={(file) => updateWorkspaceAvatar(policyID, policy.avatarURL, file as File)}
    2. Upload flow: When user clicks "Save" after cropping, AvatarCropModal calls cropAndSaveImage → onSave(newImage) → updateWorkspaceAvatar → API.write with optimistic data
    3. Optimistic update: Should immediately set policy.avatarURL to file.uri, but something is preventing this from working correctly
    4. PR Bump onyx to 3.0.46 #85248 is in staging deploy: Listed at position 36 in the chronologically ordered PR list in the Deploy Checklist
    5. Similar previous issue: Workpsace - Avatar update not reflected immediately on Overview tab after upload #76628 reported nearly identical symptoms ("Avatar update not reflected immediately on Overview tab after upload") in a previous staging deploy

    Root Cause

    The more synchronous Onyx subscriber behavior in 3.0.46 appears to create a race condition or timing issue that prevents the optimistic avatarURL update from persisting when uploading workspace avatars. The exact mechanism likely involves:

    1. The optimistic data sets policy.avatarURL to the cropped image file.uri
    2. The synchronous Onyx notifications cause re-renders or policy object updates that either:
      • Overwrite the optimistic avatar URL before it can be displayed
      • Prevent the avatar component from re-rendering with the new URL
      • Interfere with the pending action state that should protect the optimistic update

    The fix to withPolicy.tsx (moving updateLastAccessedWorkspace into useEffect) was necessary to prevent "Cannot update a component while rendering" errors, but the broader synchronous behavior change exposed this avatar upload regression.

  6. MelvinBot commented on Mar 18, 2026

    @MelvinBot
    Contributor

    Proposal

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

    When a user navigates to Workspace Settings and tries to upload a new workspace avatar image (click avatar → upload image → click "Save"), the image is not updated. This is reproducible on staging (v9.3.40-0) but not on production, indicating a regression in the current release.

    What is the root cause of that problem?

    The most likely root cause is PR #85231 ("Fix - heic context lost"), which migrated src/libs/cropOrRotateImage/index.ts (the web platform version) from the deprecated manipulateAsync API to the new class-based ImageManipulator.manipulate API from expo-image-manipulator.

    The workspace avatar upload flow is:

    1. AvatarWithImagePicker opens AttachmentPicker → user selects image
    2. validateAvatarImage validates the file (extension, size, corruption, resolution)
    3. AvatarCropModal opens → user crops → clicks Save
    4. cropOrRotateImage processes the image (crop/rotate via canvas) → creates a File object
    5. WorkspaceOverviewPage.onImageSelected calls updateWorkspaceAvatar(policyID, avatarURL, file)

    Step 4 is where PR #85231 changed the implementation. The old code used the deprecated manipulateAsync(uri, actions, options) function. The new code uses ImageManipulator.manipulate(uri) with chained .crop()/.rotate() calls, then .renderAsync() → .saveAsync().

    While both approaches ultimately go through the same expo module (NativeImageManipulatorModule.web.ts → loadImageAsync → canvas operations → blob), the migration introduces a new code path. The old manipulateAsync wrapper internally called context.release() and image.release() after saving, while the new code omits these cleanup calls. More importantly, the new code handles errors differently — if renderAsync() or saveAsync() fails, the promise rejects, and AvatarCropModal catches it at line 329 by only resetting isLoading to false without showing any error message. This means any failure in the image manipulation chain would silently fail.

    A secondary contributing factor could be PR #70740 ("Improve and simplify attachment and file validation"), which extensively refactored FileUtils.ts (including validateImageForCorruption used by the avatar validation path) and is already confirmed as the cause of deploy blocker #85671 ("No content to add" error when uploading attachments).

    Key evidence:

    • src/libs/cropOrRotateImage/index.ts:1-32 — The migrated web implementation
    • src/components/AvatarCropModal/AvatarCropModal.tsx:321-331 — The crop/save flow with silent error handling
    • src/pages/workspace/WorkspaceOverviewPage.tsx:583-588 — The onImageSelected callback calling updateWorkspaceAvatar
    • src/libs/actions/Policy/Policy.ts:1688-1731 — The updateWorkspaceAvatar action

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

    Option A (Quick fix — revert the web migration): Revert src/libs/cropOrRotateImage/index.ts back to using the deprecated manipulateAsync API. This is the safest fix for unblocking the deploy since the old code was working in production. PR #85231's HEIC fix was primarily for native platforms, and the web version change may not have been necessary.

    Option B (Fix forward): Add proper error logging and debugging to cropOrRotateImage/index.ts to identify the exact failure point in the new API chain (manipulate → renderAsync → saveAsync → fetch). Also improve AvatarCropModal's error handling (line 329) to display an error message to the user instead of silently resetting.

    I recommend Option A for the deploy blocker fix, with a follow-up investigation for Option B.

    What alternative solutions did you explore? (Optional)


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

  7. VickyStash commented on Mar 18, 2026

    @VickyStash
    Contributor

    I've just checked this issue over ad-hoc build from Onyx to 3.0.46 bump PR and wasn't able to reproduce it there. So I guess it's not related.

  8. IuliiaHerets commented on Mar 19, 2026

    @IuliiaHerets

    Chrome / v9.3.40-4 PR:85752
    Reproduced

    Screen.Recording.2026-03-19.at.12.22.23.mp4
  9. VickyStash commented on Mar 19, 2026

    @VickyStash
    Contributor

    @IuliiaHerets I think you posted a comment in the wrong issue

  10. IuliiaHerets commented on Mar 19, 2026

    @IuliiaHerets

    @VickyStash I added the wrong video, fixed it already

  11. 3 remaining items

  12. m-natarajan commented on Mar 19, 2026

    @m-natarajan

    Passed, Chrome / v9.3.40-6

    Screen.Recording.2026-03-19.at.15.26.09.mp4
  13. cristipaval commented on Mar 19, 2026

    @cristipaval
    Contributor

    Thanks! Closing it then

  14. added
    Awaiting PaymentAuto-added when associated PR is deployed to production
    and removed on Mar 23, 2026
  15. changed the title [-]Workspace settings - Photo is not updated on WS[/-] [+][Due for payment 2026-03-30] Workspace settings - Photo is not updated on WS[/+] on Mar 23, 2026
  16. melvin-bot commented on Mar 23, 2026

    @melvin-bot

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

  17. 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. 🎊

  18. melvin-bot commented on Mar 23, 2026

    @melvin-bot

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

  19. melvin-bot commented on Mar 23, 2026

    @melvin-bot

    Triggered auto assignment to @mallenexpensify (Awaiting Payment)

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