Uncaught DOMException: Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.
hthetiot opened this issue · 13 comments
Please read first!
Please use discuss-webrtc for general technical discussions and questions.
- I have provided steps to reproduce (e.g. a link to a jsfiddle)
- I have provided browser name, version and adapter.js version
- This issue only happens when adapter.js is used
Note: If the checkboxes above are not checked (which you do after the issue is posted), the issue will be closed.
Versions affected
-
Chrome 81.0.4044.129
-
adapter.js from
https://webrtc.github.io/adapter/adapter-latest.js
Description
Cause Uncaught DOMException: Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.
when calling peerConnection.removeTrack
with RTCRtpSender
from getSenders
.
Steps to reproduce
var senders = peerConnection.getSenders();
stream.getTracks().forEach((track) => {
senders.forEach((sender) => {
if (sender.track === track) {
peerConnection.removeTrack(sender);
}
});
});
Only when https://webrtc.github.io/adapter/adapter-latest.js
is loaded.
Expected results
Remove Sender peerConnection from and properly when https://webrtc.github.io/adapter/adapter-latest.js
is not loaded.
Actual results
Cause Uncaught DOMException: Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.
Caused by https://webrtc.github.io/adapter/adapter-latest.js:892
// We can not yet check for sender instanceof RTCRtpSender
// since we shim RTPSender. So we check if sender._pc is set.
if (!sender._pc) {
throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' + 'does not implement interface RTCRtpSender.', 'TypeError');
}
Note: sender.replaceTrack(null) also fail.
Current workaround:
var senders = peerConnection.getSenders();
stream.getTracks().forEach((track) => {
senders.forEach((sender) => {
if (sender.track === track) {
// Fix Uncaught DOMException: Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.
if (typeof window.adapter) {
sender._pc = peerConnection;
}
peerConnection.removeTrack(sender);
}
});
});
Note: sender.replaceTrack(null)
fail to properly remove the track on Chrome 81.0.4044.129
can't reproduce on with https://webrtc.github.io/samples/src/content/peerconnection/pc1/
var senders = pc1.getSenders();
localStream.getTracks().forEach((track) => {
senders.forEach((sender) => {
if (sender.track === track) {
pc1.removeTrack(sender);
}
});
});
after making a call. In M81 checking window.RTCPeerConnection.prototype.getSenders
should return ƒ getSenders() { [native code] }
(i.e. no shimming), does it do that for you?
I confirm I do not reproduce with https://webrtc.github.io/samples/src/content/peerconnection/pc1/ and that window.RTCPeerConnection.prototype.getSenders
does return ƒ getSenders() { [native code] }
(i.e. no shimming).
I'm not sure I ended up fixing it but I cannot reproduce anymore despite been able to reproduce several time before creating the issue (I did change some of my implementation since then, I think that why) I'm closing for now and will re-open if it append again and I have a full sample not partial to reproduce.
Thank you @fippo
I can reproduce using https://webrtc.github.io/samples/src/content/peerconnection/pc1/ by selecting Unified-Plan. See capture above. I think yesterday I did not reproduce because I did not select Unified-Plan on the sample. The weird part is on my side I'm not using Unified-Plan but sdpSemantics: plan-b
and "bundlePolicy": 'max-compat'
.
Updated workaround:
// Using removeStream
if (
// @ts-ignore
typeof peerConnection.removeStream === 'function' &&
typeof window.adapter !== 'undefined' &&
window.adapter.browserDetails.browser === 'chrome'
) {
// @ts-ignore
peerConnection.removeStream(streamObj.stream);
// Using sender removeTrack
} else {
var senders = peerConnection.getSenders();
streamObj.stream.getTracks().forEach((track) => {
senders.forEach((sender) => {
if (sender.track === track) {
peerConnection.removeTrack(sender);
}
});
});
}
Still can't reproduce. This looks like it is running into some weird interaction in ħere
Can you step through this and check it runs into this?
It would be interesting to see if the error is the native one or https://github.com/webrtcHacks/adapter/blob/master/src/js/chrome/chrome_shim.js#L633
If its the native one, what is the value of the first argument to the native replaceTrack call?
you have three senders there. And the transport of the sender you're trying to remove is null.
And pc1.removeTrack shows this15
which suggests its https://github.com/webrtc/adapter/blob/gh-pages/adapter-7.5.0.js#L861 which suggests its not running into https://github.com/webrtc/adapter/blob/gh-pages/adapter-7.5.0.js#L689
How does adapter.browserDetails looks like, in particular the version?
Ok I got with your instructions, I was running the console with the device toolbar open without realizing it. That why it came and disappeared wihout trace yesterday,
Because it is using user agent sniffing instead of features detection it caused bad detection of the browser version.
This is basicly a false positive I would say. Closing then.
Thank you @fippo for the pointer.
there is probably room for improvement when the detected version is null (from ua sniffing) and it still looks like chrome (from feature detecetion). Interesting
That been said, I wonder what append on all this Chromium based browser with modifed userAgent...
Final dirty workaround for using adapter and the console with the device toolbar using custom userAgent on chrome:
var tryUsingRemoveStream = false;
// Using sender removeTrack
try {
var senders = peerConnection.getSenders();
streamObj.stream.getTracks().forEach((track) => {
senders.forEach((sender) => {
if (sender.track === track) {
peerConnection.removeTrack(sender);
}
});
});
} catch (err) {
if (err.message === 'Argument 1 of RTCPeerConnection.removeTrack does not implement interface RTCRtpSender.') {
tryUsingRemoveStream = true;
} else {
throw err;
}
}
// Using removeStreamx
if (
// @ts-ignore
tryUsingRemoveStream && typeof peerConnection.removeStream === 'function'
) {
// @ts-ignore
peerConnection.removeStream(streamObj.stream);
}