Error: connect() already called

I had a crash today on my server and the following error was the only message that was logged in the file for several times. I don’t have the complete log so I have no idea why or when is it happening. Can this be the cause of the crash?

Error: connect() already called
    at Channel._processMessage (../node_modules/mediasoup/lib/Channel.js:284:19)
    at Socket.Channel._socket.on (../node_modules/mediasoup/lib/Channel.js:101:13)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at Socket.Readable.push (_stream_readable.js:208:10)
    at Pipe.onread (net.js:601:20)

BTW I’m using v3.0.12.

You may be calling connect() twice.

What about the crash? Is there any crash dump to find the cause?

Let’s clarify what a “crash” means. For me, a crash is a mediasoup-worker (C++ binary) crash. But when that happens you should see some error log such as “Channel error: xxxxxxx” or similar, and I do not see it above in your log.

So I expect that it’s just your Node app the one which is “exiting” due to a non caught exception. I don’t know which Node version you use, but AFAIK latest one may terminate the Node process when a Promise rejection is not handled or when an async function throws and there is no try catch to handle it in your app.

mediasoup cannot generate “crash dumps” by itself. If there was a real crash (mediasoup-worker C++ binary crashed) then:

  • In OSX you can see crash reports in ~/Library/Logs/DiagnosticReports.
  • In Linux search for “enable core dump in Linux”.

BTW if you found a real crash (mediasoup-worker C++ subprocess died) please report it in GitHub as it would be a real bug.

You may be calling connect() twice.

Yeah, the error keeps happening and I could not find the scenario that causes the connect is called again. I even don’t know if it is consumer or producer but I can guess it must be some thing related to connection interruption. So I ended up checking the transport.connectionState in the client side and also transport.dtlsState in the server side to avoid twice connect.

Regarding the crash, the core dump was disabled at the time of crash and it never happened again.

Thanks for the tips.

If the network has disconnected and you don’t close the server side WebRtcTransport and call connect() on it again, it will fail. To clarify, the mediasoup server side WebRtcTransport is not “closed” when the Internet connection of the client is closed, neither it’s disconnected (since mediasoup is ICE-Lite so it does not know whether the remote endpoint has disconnected at transport level or not).

This does not clarify whether the mediasoup-worker process crashed (so a mediasoup bug) or not.

BTW I’ve seen the “Error: connect() already called” error in the mediasoup demo server, so something can be improved. However it was not a “crash” at all but just a JavaScript exception due to wrong mediasoup API usage. So no issue or bug in mediasoup so far.

I could reproduce the error. When two producers or consumers are created at the same time and over the same transport in the client side then the transport.on('connect') event is fired twice. Thus, two simultaneous requests are sent to the server and as a result, dual call to the transport.connect() happens.

However the two producers/consumers are connected successfully but better to avoid this somehow, by checking the previous calls to the transport for instance. Checking the transport.dtlsState, as I mentioned before, won’t help in this scenario.

That cannot (should not) happen. In mediasoup-client, calls to transport.produce() (or consume()) are enqueued and the second one does not start until the previous one completes. The first call to transport.produce() will trigger the transport “connect” event (and just it).

This is super tested. If you see it failing, please paste debug logs in client side that demonstrate the bad order of methods and events. But this is really super tested.

Sorry, my fault. For me the bug is about the duplication of the transports. Here’s the simplified code of the scenario:

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);
}

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

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

Create the send transport first and, once done, create the audio and video producers as in the demo.

Correct :+1: