electron / electron/electron

setDisplayMediaRequestHandler useSystemPicker crashes after custom handler capture on macOS

Open
#51,571 7 comments 0 reactions 0 assignees View on GitHub
42-x-y bug :beetle: component/desktopcapturer crash :boom: has-repro-gist platform/macOS stale
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.