Error: connect() already called

I am having the exact same issue listed here.

I read over the responses and solution there and I don’t really understand why there is an issue with what he is doing. (I am doing something similar, I am creating a sending and receiving transport at the same time which is likely generating the error).

This was his code, I am using it for simplicity.

let  transport;

async function publish(track) {
  if (!transport) {
    transport = await device.createSendTransport();
    transport.on('connect', connectTransport);
  }
  await transport.produce({ track });
}

function startMic() {
  ...
  publish(audioTrack);
}

function startWebcam() {
  ...
  publish(videoTrack);
}

Why is this an issue? When the connect event is emitted on the client side, connectTransport is called which makes a request to the server with the transport’s id and dtlsParameters. On the server, it uses the id to find the transport and then calls transport.connect({dtlsParameters}). This shouldn’t cause an issue with connect being called twice as the id is being checked before it is called.

For example, if startMic is called and creates a transport with an id of “1”. Then startWebcam is called creating a transport with an id of “2”. There should be no issue, as the server will use those id’s to connect. connect() should never be be being called twice.

Additionally, there should be a way to check whether the transport is already connected server side. Obviously there is a check going on internally in order to produce that error, is there a way we can check? Even if the client side code is fixed, we should be able to check server side as the client can make any request they want. Would you suggest storing connected state in appData?

The issue is in server side. Obviously you are calling connect() multiple times in the same server side transport. You must create a new server side transport for each client side transport, you cannot reuse them.

In your code snippet above you are using the same transport in client side for audio and video, which is fine, and not two transports.

Again: go to your server side and check why transport.connect() is being called twice on the same transport.

The issue is in server side. Obviously you are calling connect() multiple times in the same server side transport. You must create a new server side transport for each client side transport, you cannot reuse them.

I think I am.

In your code snippet above you are using the same transport in client side for audio and video, which is fine, and not two transports.

On the other thread Error: connect() already called you say

That’s indeed a bug in your code since you are creating separate send transports for audio and video.

I have posted the same code (just as an example here). How is it different?


There are two issue at hand here.

  1. Based on the code snippet, I don’t think connect() should be being called twice. Since transports are refered to by id this shouldn’t be an issue:

If startMic() and startWebcam() are called immediately one after the other, then two transports are created which leads to dual call to connectTransport().

startMic and startWebcam should crete unique id’s of transports. You should be able to create a separate transport for audio and video if you like.

  1. Regardless of the code on the client side, you should be able to check server side if connect() was called. If this check isn’t possible, then you are trusting the client not to call connectTransport twice. We shouldn’t need to trust the client. There should be a mechanism server side to check if connect has been called to prevent an error from occurring.

To make it simpler lets use the following example.

const  transports = [];

async function publish(track) {
    const transport = await device.createSendTransport();
    transport.on('connect', connectTransport);
    transports.push(transport);
    await transport.produce({ track });
}

function startMic() {
  ...
  publish(audioTrack);
}

function startWebcam() {
  ...
  publish(videoTrack);
}

Well, that’s not a bug but probably undesirable behavior.

What can I say? I am not in front of your server side code. I just can guarantee that Error: connect() already called just happens if you call transport.connect() twice on the same server side transport.

You can perfectly do that if you like.

We are not gonna add getters in mediasoup just to avoid app-level errors. That’s our philosophy (do less, do it fine). You should check why you client side is sending connect signal twice for the same transport (check your sent messages from client to server) and/or why your server side code is calling connect() twice on the same transport.

What can I say? I am not in front of your server side code. I just can guarantee that Error: connect() already called just happens if you call transport.connect() twice on the same server side transport.

Fair enough I will do more debugging and try to figure out the issue.

We are not gonna add getters in mediasoup just to avoid app-level errors. That’s our philosophy (do less, do it fine). You should check why you client side is sending connect signal twice for the same transport (check your sent messages from client to server) and/or why your server side code is calling connect() twice on the same transport.

Again, I don’t think we should have to rely on the client. Should our client side code be written so this doesn’t happen? Yes, it should. But, it’s on the client. We can’t trust the client not to make the same request twice. There should be a way server side to do the check.

If you think we should just store it ourselves or using a try/catch pattern, I strongly disagree however I recognize it is your library. Thank you for the help.

On await transport.connect() success, you can do:

transport.appData.connected = true;

And then check that flag if attempted to call the same again.

Said that, I don’t want to add a transport.connected getter because people may thing that it means “everything is connected at ICE and DTLS” level while it’s not.

I think this is a decent solution. I will note, however, this isn’t the source of truth (the source of truth is at the c++ level). But it should work.

Maybe add this to demo and/or docs?

This is the source of truth because if await transport.connect() completes you know that it can be properly processed in C++.

Now, if you call twice to transport.connect() while the first call did not even complete… that’s a different problem.

I cannot add to the demo something that fixes or improves nothing. That “issues” does not happen in the demo. And I cannot document “use transport.appData.connected to blablabla” because users can use appData for whatever thing they wish.

Ah, I assumed you were do to the other post.

BTW I’ve seen the “Error: connect() already called” error in the mediasoup demo server, so something can be improved.

Ok. I understand. Hopefully people will see this thread if they Google search. Thanks.

I’ve not seen that for a while. If that happens there is a but in the demo app code. I don’t want to hide it with a check. The check is already there: transport.connect() rejects so the server catches the exception and tells the client.

I’d probably do a check (with the app data) and if it fails, then handle the error by logging it. But the fact that you haven’t seen it in a while, does indicate that I likely have an issue in my front end code more than an underlying bug in mediasoup.