fix: Failed to set remote offer sdp: Duplicate a=mid value 'datachannel' error#371
fix: Failed to set remote offer sdp: Duplicate a=mid value 'datachannel' error#371evgmel wants to merge 1 commit into
Conversation
Steps to reproduce1. SetupAny application that creates multiple data consumers on a single receive 2. Inject a one-shot failureIn if (!this._hasDataChannelMediaSection) {
this._remoteSdp.receiveSctpAssociation();
// --- temporary: simulate first-call failure ---
if (!(this as any).__debugFirstDataChannelFailed) {
(this as any).__debugFirstDataChannelFailed = true;
throw new Error('Simulated first receiveDataChannel failure');
}
// --- end temporary ---
const offer = { type: 'offer' as RTCSdpType, sdp: this._remoteSdp.getSdp() };
await this._pc.setRemoteDescription(offer);
// ...
}3. Trigger the bugCall // First call — hits the injected throw after receiveSctpAssociation().
// The caller catches/swallows the error.
try {
await recvTransport.consumeData(optionsA);
} catch {
// error swallowed — transport SDP is now corrupted
}
// Second call — receiveSctpAssociation() is called again because
// _hasDataChannelMediaSection is still false, producing a duplicate
// a=mid:'datachannel' in the SDP.
await recvTransport.consumeData(optionsB);
// ^ throws: "Duplicate a=mid value 'datachannel'"4. Observe the errorThe second |
|
Hello @ibc ! Could you please take a look at the PR? |
|
This solution is not valid because it fails if const options = {
negotiated: true,
id: streamId,
ordered,
maxPacketLifeTime,
maxRetransmits,
protocol,
};
const dataChannel = this._pc.createDataChannel(label!, options); |
|
@ibc In our app we create 2 different data consumers for different data producers on a receive transport. I've checked - |
|
I'm sorry but I will close this PR. Rationale is the following: mediasoup-client was absolutely never designed to be resilient to errors in This PR covers a single use case ( If |
This PR fixes
Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote offer sdp: Duplicate a=mid value 'datachannel'error.Summary
When
receiveDataChannel()fails afterreceiveSctpAssociation()mutates theinternal
RemoteSdpstate but before_hasDataChannelMediaSectionis set totrue, any subsequentreceiveDataChannel()call adds a secondm=applicationsection withmid=datachannelto the SDP. The browser thenrejects the offer with:
After this point the transport is permanently broken and cannot create any new
data channels.
Root cause
In every handler (
Chrome111,Chrome74,Safari12,Firefox120,ReactNative106) thereceiveDataChannel()method follows this sequence:receiveSctpAssociation()unconditionally pushes a newOfferMediaSectionwith
mid: 'datachannel'into_mediaSectionsand_midToIndex. If step 2throws, the section remains in the SDP but the guard flag stays
false. Thenext call enters the
ifblock again, callsreceiveSctpAssociation()again,and produces a duplicate
a=mid.The same pattern exists in
sendSctpAssociation()for the send direction.The fix in the PR
The fix ensures that even if
_hasDataChannelMediaSectionis out of sync with theactual SDP state, the media section is never duplicated (idempotent).