Bug 174327 - Adding, removing, and then adding back same MediaStreamTrack throws InvalidAccessError
Summary: Adding, removing, and then adding back same MediaStreamTrack throws InvalidAc...
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebRTC (show other bugs)
Version: Safari Technology Preview
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
Keywords: InRadar
Depends on:
Reported: 2017-07-10 16:22 PDT by Mark Roberts
Modified: 2019-05-01 12:18 PDT (History)
4 users (show)

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Mark Roberts 2017-07-10 16:22:32 PDT
It should be possible to add a MediaStreamTrack, remove it, and then add it back to an RTCPeerConnection. See the following code:

    (async () => {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
      const [track] = stream.getTracks()

      const pc = new RTCPeerConnection()

      console.log('1. addTrack(track, stream)')
      const sender = pc.addTrack(track, stream)

      console.log('2. removeTrack(sender)')
      if (sender.track !== null) {
        console.error('The RTCRtpSender\'s track should be set to null')

      console.log('3. addTrack(track, stream)')
      pc.addTrack(track, stream)


Expected output:

    1. addTrack(track, stream) 
    2. removeTrack(sender) 
    3. addTrack(track, stream) 

Actual output (Safari):

    1. addTrack(track, stream) 
    2. removeTrack(sender) 
    The RTCRtpSender's track should be set to null
    3. addTrack(track, stream) 
    Unhandled Promise Rejection: InvalidAccessError (DOM Exception 15): The object does not support the operation or argument.

(Note: In Firefox, I mostly get the expected output, except I also get the "The RTCRtpSender's track should be set to null" error.)

FWIW, I tried to workaround this by calling `sender.replaceTrack` in Step 3 instead of `sender.addTrack`. Although the code prints "Success!" in that case, I later get "Unhandled Promise Rejection: InvalidStateError (DOM Exception 11): The object is in an invalid state."
Comment 1 Radar WebKit Bug Importer 2017-07-12 10:34:51 PDT
Comment 2 Mark Roberts 2018-04-17 11:36:32 PDT
Here is a potential workaround: instead of just calling `removeTrack`, call `replaceTrack(null)` on the RTCRtpSender first. For example:


If you do this and then call at least `createOffer` and `setLocalDescription`, then you can remove and add back the same MediaStreamTrack.
Comment 3 Ben 2019-05-01 02:36:01 PDT
This is still an issue in Safari 12.1

The workaround doesn't work for me. Mark, setting sender.replaceTrack(null) works for you in Safari 12.1? Any other workaround to add/remove/add same track?
Comment 4 Ben 2019-05-01 09:11:31 PDT
If you add a track with let sender = pc.addTrack(track, stream) and remove it with pc.removeTrack(sender) you can't add a track of the same kind again. The sender has the new track and the transceiver direction is sendrecv but the sdp doesn't have the track (no ssrc lines).

To reproduce:
const stream = await navigator.mediaDevices.getUserMedia({ video: true })
const [track] = stream.getTracks()
let sender = pc.addTrack(track, stream);
// negotiate
// you can also try sender.replaceTrack(null) and track.stop() but it doesn't help.
// negotiate
const stream2 = await navigator.mediaDevices.getUserMedia({ video: true })
const [track2] = stream2.getTracks()
let sender2 = pc.addTrack(track2, stream2);
let offer = await this.pc.createOffer();
// direction of the video section in the sdp is inactive and there are no ssrc lines.

Youenn, is there a workaround?
Comment 5 youenn fablet 2019-05-01 09:34:36 PDT
I think the workaround regressed in Safari 12.1 unfortunately.
This should be fixed in Safari Tech Preview and should also be ok on latest MacOS/iOS betas.
I am closing this issue, please reopen if you still see that issue in STP or in latest MacOS/iOS betas.
Comment 6 Ben 2019-05-01 12:18:23 PDT

How come major bugs like this not detected with regression tests?
How bugs that are reported during beta reach stable?