setDisplayMediaRequestHandler useSystemPicker crashes after custom handler capture on macOS
- Dominant language
- C++
- Stars
- 123k
- Forks
- 17.5k
- Avg merge
- 14h 28m
- Merged PRs (30d)
- 870
Description
### Preflight Checklist
- [x] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [x] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [x] I have searched the issue tracker for a bug report that matches the one I want to file, without success.
### Electron Version
42.0.1, 39.8.10
### What operating system are you using?
macOS
### Operating System Version
macOS 26.4 / Darwin 25.4.0
### What arch are you using?
arm64 (Apple Silicon)
### Last Known Working Electron version
N/A
### Expected Behavior
An app should be able to use a custom `setDisplayMediaRequestHandler(..., { useSystemPicker: false })` flow for one `getDisplayMedia()` request, stop all returned tracks, and then later switch to `setDisplayMediaRequestHandler(..., { useSystemPicker: true })` for a subsequent `getDisplayMedia()` request without hanging or crashing.
### Actual Behavior
After a custom handler capture completes and all tracks are stopped, switching the same Electron session back to `useSystemPicker: true` can crash the process when a source is selected in the macOS system picker.
The crash is native and cannot be caught in JavaScript:
```text
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: ...> was mutated while being enumerated.'
*** First throw call stack:
(
0 CoreFoundation __exceptionPreprocess
1 libobjc.A.dylib objc_exception_throw
2 CoreFoundation -[__NSSingleObjectEnumerator description]
3 ScreenCaptureKit -[SCContentSharingPicker contentPickerDidSelectFilter:forStream:]
4 ReplayKit -[RPScreenRecorder contentPickerDidSelectFilter:forStream:]
5 ReplayKit -[RPDaemonProxy contentPickerDidSelectFilter:forStream:]
...
)
Electron exited with signal SIGTRAP
```
### To Reproduce
1. Clone the gist below.
2. Run `npm install`.
3. Run `npm start`.
4. Click `1. Custom picker capture`.
5. In the in-app custom source list, select a window.
6. Wait for the local preview to start.
7. Click `2. Stop tracks`.
8. Click `3. System picker capture`.
9. In the macOS system picker, select the same window.
10. The app crashes with the native ScreenCaptureKit stack above.
Control behavior: if `3. System picker capture` is used first after app start, the system picker works.
### Testcase Gist URL
https://gist.github.com/3777de2ac0a21630326fda9039e9762e
### Additional Information
The minimal repro does not use any app-specific code or WebRTC publishing. It only uses:
- `desktopCapturer.getSources()` for the custom source list
- `session.defaultSession.setDisplayMediaRequestHandler(handler, { useSystemPicker: false })`
- `navigator.mediaDevices.getDisplayMedia()`
- `MediaStreamTrack.stop()`
- then `session.defaultSession.setDisplayMediaRequestHandler(handler, { useSystemPicker: true })`
- then `navigator.mediaDevices.getDisplayMedia()` again
I also tested stronger cleanup before switching back to system picker, including clearing references and stopping tracks. The crash still occurs, suggesting the issue is in the same-session transition from a custom handler capture to the macOS system picker.
Contributor guide
Assessment
This issue has not been assessed yet.