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
[Due for payment 2026-03-19] [$250] Attachments-Video is not playing when opened from the attachments history, play/pause blinks #80949
Version Number: 9.3.11-4 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/projects/2219752/folder/13176710/test-cases/41236953 Email or phone of affected tester (no customers): N/A Issue reported by: Applause Internal Team Bug source: Exploratory - Significant User Experience Deterioration Device used: iPhone 15 iOS 26.2 App Component: Other
Action Performed:
Sign in to ND
Create a chat with another user
Send some images and a video in the chat
Open and play the video, close it
Open any other attachment and navigate through the attachments until you reached the video
Expected Result:
The video starts playing, when opened from the attachments history
Actual Result:
Video can't be played if opened from the attachments history, play/pause button blinks. Sometimes the whole attachment or control modal at the bottom blink
Please re-state the problem that we are trying to solve in this issue.
When navigating through attachments in the carousel on iOS native and reaching a video by swiping (not opening directly), the video cannot be played. The play/pause button blinks, and sometimes the entire attachment or control modal at the bottom blinks.
What is the root cause of that problem?
There are two compounding bugs, both specific to native:
if (onNavigate) {
onNavigate(item); // first call
}
onNavigate?.(item); // duplicate call
The web version at index.tsx:109-111 correctly calls it only once. Each onNavigate triggers Navigation.navigate (via onCarouselAttachmentChange in ReportAttachmentModalContent.tsx:83), causing double route navigation per swipe. This creates unnecessary re-renders and route transitions that destabilize the video initialization flow.
Bug 2: Feedback loop in AttachmentView's video URL registration
The useEffect in AttachmentView/index.tsx:157-163 has currentlyPlayingURL, updateCurrentURLAndReportID, and playVideo in its dependency array, but only updateCurrentURLAndReportID is actually used in the effect body. This creates a feedback loop:
Swiping to a video triggers this effect, which calls updateCurrentURLAndReportID(videoURL, reportID)
This sets currentlyPlayingURL in the PlaybackContext, which changes the updateCurrentURLAndReportID callback reference (since currentlyPlayingURL is in its useCallback deps at PlaybackContext/index.tsx:66)
Both currentlyPlayingURL and the new updateCurrentURLAndReportID reference re-trigger the effect
Meanwhile, resetVideoPlayerData at PlaybackContext/index.tsx:97-119 also fires on currentlyPlayingURL change and may detect a route mismatch (since Navigation.navigate from the double onNavigate is async), triggering a full player reset that sets currentlyPlayingURL = null
This null value re-triggers the AttachmentView effect, restarting the cycle
Each cycle calls video.pause() then video.play(), toggling isPlaying which directly drives the play/pause button icon (VideoPlayerControls/index.tsx:112), causing the visible blinking.
An additional contributing factor: the native Pager computes isFocused from two separate state sources (Pager/index.tsx:136) -- activePageIndex (updated via useEffect with one render-frame delay) and activeAttachmentID (updated immediately). This causes isFocused to briefly be false for all pages during transitions, adding extra effect triggers. The web version avoids this by only checking activeAttachmentID.
What changes do you think we should make in order to solve the problem?
Fix the double onNavigate call in AttachmentCarouselView/index.native.tsx:49-52: Remove the duplicate onNavigate?.(item) call at line 52, keeping only the guarded call at lines 49-51. This matches the web version's behavior.
Remove currentlyPlayingURL and playVideo from the AttachmentView useEffect dependency array at AttachmentView/index.tsx:163: These values are not used in the effect body and their presence creates the feedback loop. The effect should only re-run when isFocused, source, reportID, or updateCurrentURLAndReportID actually change in ways relevant to the effect's purpose.
Consider stabilizing updateCurrentURLAndReportID by removing currentlyPlayingURL from its useCallback dependency array in PlaybackContext/index.tsx:66. The function reads currentlyPlayingURL to decide whether to pause, but this could use a ref instead of a state dependency, preventing the callback reference from changing on every URL update.
What alternative solutions did you explore? (Optional)
Synchronizing activePageIndex directly in the onPageSelected callback instead of via useEffect on initialPage in the Pager. This would eliminate the isFocused flicker but doesn't address the core feedback loop.
Using useRef for currentlyPlayingURL inside updateCurrentURLAndReportID to avoid recreating the callback. This would stabilize the reference but still leaves currentlyPlayingURL as a direct dependency in the AttachmentView effect.
Next Steps for Contributor+ team: Reply with @MelvinBot implement this to create a draft PR, or @MelvinBot <your feedback> to refine this analysis.
changed the title [-]Attachments-Video is not playing when opened from the attachments history, play/pause blinks[/-][+][$250] Attachments-Video is not playing when opened from the attachments history, play/pause blinks[/+]on Mar 5, 2026
[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.
Link to discussion: N/A — Not critical. Users can still view the video by opening it directly rather than swiping through the carousel.
[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.
[BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.
Activity
melvin-bot commentedon Mar 5, 2026
Triggered auto assignment to @RachCHopkins (
Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.MelvinBot commentedon Mar 5, 2026
Proposal
Please re-state the problem that we are trying to solve in this issue.
When navigating through attachments in the carousel on iOS native and reaching a video by swiping (not opening directly), the video cannot be played. The play/pause button blinks, and sometimes the entire attachment or control modal at the bottom blinks.
What is the root cause of that problem?
There are two compounding bugs, both specific to native:
Bug 1: Double
onNavigatecall (native only)In
AttachmentCarouselView/index.native.tsx:49-52,onNavigateis called twice per page change:The web version at
index.tsx:109-111correctly calls it only once. EachonNavigatetriggersNavigation.navigate(viaonCarouselAttachmentChangeinReportAttachmentModalContent.tsx:83), causing double route navigation per swipe. This creates unnecessary re-renders and route transitions that destabilize the video initialization flow.Bug 2: Feedback loop in AttachmentView's video URL registration
The
useEffectinAttachmentView/index.tsx:157-163hascurrentlyPlayingURL,updateCurrentURLAndReportID, andplayVideoin its dependency array, but onlyupdateCurrentURLAndReportIDis actually used in the effect body. This creates a feedback loop:updateCurrentURLAndReportID(videoURL, reportID)currentlyPlayingURLin the PlaybackContext, which changes theupdateCurrentURLAndReportIDcallback reference (sincecurrentlyPlayingURLis in itsuseCallbackdeps atPlaybackContext/index.tsx:66)currentlyPlayingURLand the newupdateCurrentURLAndReportIDreference re-trigger the effectresetVideoPlayerDataatPlaybackContext/index.tsx:97-119also fires oncurrentlyPlayingURLchange and may detect a route mismatch (sinceNavigation.navigatefrom the doubleonNavigateis async), triggering a full player reset that setscurrentlyPlayingURL = nullEach cycle calls
video.pause()thenvideo.play(), togglingisPlayingwhich directly drives the play/pause button icon (VideoPlayerControls/index.tsx:112), causing the visible blinking.An additional contributing factor: the native Pager computes
isFocusedfrom two separate state sources (Pager/index.tsx:136) --activePageIndex(updated viauseEffectwith one render-frame delay) andactiveAttachmentID(updated immediately). This causesisFocusedto briefly befalsefor all pages during transitions, adding extra effect triggers. The web version avoids this by only checkingactiveAttachmentID.What changes do you think we should make in order to solve the problem?
Fix the double
onNavigatecall inAttachmentCarouselView/index.native.tsx:49-52: Remove the duplicateonNavigate?.(item)call at line 52, keeping only the guarded call at lines 49-51. This matches the web version's behavior.Remove
currentlyPlayingURLandplayVideofrom the AttachmentView useEffect dependency array atAttachmentView/index.tsx:163: These values are not used in the effect body and their presence creates the feedback loop. The effect should only re-run whenisFocused,source,reportID, orupdateCurrentURLAndReportIDactually change in ways relevant to the effect's purpose.Consider stabilizing
updateCurrentURLAndReportIDby removingcurrentlyPlayingURLfrom itsuseCallbackdependency array inPlaybackContext/index.tsx:66. The function readscurrentlyPlayingURLto decide whether to pause, but this could use a ref instead of a state dependency, preventing the callback reference from changing on every URL update.What alternative solutions did you explore? (Optional)
activePageIndexdirectly in theonPageSelectedcallback instead of viauseEffectoninitialPagein the Pager. This would eliminate theisFocusedflicker but doesn't address the core feedback loop.useRefforcurrentlyPlayingURLinsideupdateCurrentURLAndReportIDto avoid recreating the callback. This would stabilize the reference but still leavescurrentlyPlayingURLas a direct dependency in the AttachmentView effect.Next Steps for Contributor+ team: Reply with
@MelvinBot implement thisto create a draft PR, or@MelvinBot <your feedback>to refine this analysis.melvin-bot commentedon Mar 5, 2026
Current assignee @abzokhattab is eligible for the External assigner, not assigning anyone new.
[-]Attachments-Video is not playing when opened from the attachments history, play/pause blinks[/-][+][$250] Attachments-Video is not playing when opened from the attachments history, play/pause blinks[/+]23 remaining items
melvin-bot commentedon Mar 19, 2026
Payment Summary
Upwork Job
BugZero Checklist (@mallenexpensify)
mallenexpensify commentedon Mar 20, 2026
Payment Summary
Contributor+: @abzokhattab due $250 via NewDot
@abzokhattab plz complete the BZ checklist and tag me in a post once you have. Thx
melvin-bot commentedon Mar 24, 2026
@mallenexpensify Whoops! This issue is 2 days overdue. Let's get this updated quick!
mallenexpensify commentedon Mar 25, 2026
@abzokhattab 👀 above plz
abzokhattab commentedon Mar 26, 2026
BugZero Checklist:
[Contributor] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.
Link to comment: https://github.com/Expensify/App/pull/63352/changes#r2996090093
[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.
Link to discussion: N/A — Not critical. Users can still view the video by opening it directly rather than swiping through the carousel.
[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.
[BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.
Link to issue: https://github.com/Expensify/Expensify/issues/616716
Regression Test Proposal
Precondition:
Test:
Do we agree 👍 or 👎
Zapier Logs
Run ID: 00040eee-bf66-ad10-c1d6-6d80f9072dd4abzokhattab commentedon Mar 26, 2026
@mallenexpensify done
mallenexpensify commentedon Mar 26, 2026
Thanks @abzokhattab
^ Test case created
twisterdotcom commentedon Mar 26, 2026
@abzokhattab has submitted payment for this report on ND here.
SO: https://stackoverflowteams.com/c/expensify/questions/7582
Zapier Logs
Run ID: 00040eee-ec14-a0e9-21c9-e56116012ae4