Describe the bug
Event listeners registered in the Room constructor (e.g. devicechange on navigator.mediaDevices) are never removed unless handleDisconnect is called. When a Room instance is destroyed before a disconnect event fires — for example during component unmount, route change, or explicit cleanup — the listener remains attached to the global navigator.mediaDevices object.
This causes a memory leak and can trigger callbacks on a dead room instance, leading to unexpected side effects or errors in long-lived applications that create and destroy multiple room instances.
Reproduction
- Create a Room instance and connect it to a LiveKit server.
- Destroy or discard the Room instance without calling disconnect() — e.g. replace the reference, unmount the component, or navigate away.
- Inspect navigator.mediaDevices event listeners (e.g. via browser DevTools or a test spy).
- Observe that the devicechange listener from the destroyed room is still registered.
Logs
System Info
https://github.com/livekit/client-sdk-js
Tested on Chrome, macOS.
Severity
serious, but I can work around it
Additional Information
No response
Describe the bug
Event listeners registered in the Room constructor (e.g. devicechange on navigator.mediaDevices) are never removed unless handleDisconnect is called. When a Room instance is destroyed before a disconnect event fires — for example during component unmount, route change, or explicit cleanup — the listener remains attached to the global navigator.mediaDevices object.
This causes a memory leak and can trigger callbacks on a dead room instance, leading to unexpected side effects or errors in long-lived applications that create and destroy multiple room instances.
Reproduction
Logs
System Info
Severity
serious, but I can work around it
Additional Information
No response