title: Failed to set remote answer sdp: Called in wrong state: stable
body: <p>I am trying to write a <code>WebRTC</code> application using <code>socket.io</code>.</p>
  <p>The <em>signalling server</em> is written in python and looks like this.</p>
  <pre><code>import socketio
  import uvicorn
  from starlette.applications import Starlette
  
  ROOM = 'room'
  
  
  sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*')
  star_app = Starlette(debug=True)
  app = socketio.ASGIApp(sio, star_app)
  
  
  @sio.event
  async def connect(sid, environ):
      await sio.emit('ready', room=ROOM, skip_sid=sid)
      sio.enter_room(sid, ROOM)
  
  
  @sio.event
  async def data(sid, data):
      await sio.emit('data', data, room=ROOM, skip_sid=sid)
  
  
  @sio.event
  async def disconnect(sid):
      sio.leave_room(sid, ROOM)
  
  
  if __name__ == '__main__':
      uvicorn.run(app, host='0.0.0.0', port=8003)
  </code></pre>
  <p>The <em>client side</em> looks like this</p>
  <pre><code>&lt;script&gt;
      const SIGNALING_SERVER_URL = 'http://127.0.0.1:8003?session_id=1';
      // WebRTC config: you don't have to change this for the example to work
      // If you are testing on localhost, you can just use PC_CONFIG = {}
      const PC_CONFIG = {};
  
      // Signaling methods
      let socket = io(SIGNALING_SERVER_URL, {autoConnect: false});
  
      socket.on('data', (data) =&gt; {
          console.log('Data received: ', data);
          handleSignalingData(data);
      });
  
      socket.on('ready', () =&gt; {
          console.log('Ready');
          // Connection with signaling server is ready, and so is local stream
          createPeerConnection();
          sendOffer();
      });
  
      let sendData = (data) =&gt; {
          socket.emit('data', data);
      };
  
      // WebRTC methods
      let pc;
      let localStream;
      let remoteStreamElement = document.querySelector('#remoteStream');
  
      let getLocalStream = () =&gt; {
          navigator.mediaDevices.getUserMedia({audio: true, video: true})
              .then((stream) =&gt; {
                  console.log('Stream found');
                  localStream = stream;
                  // Connect after making sure that local stream is availble
                  socket.connect();
              })
              .catch(error =&gt; {
                  console.error('Stream not found: ', error);
              });
      }
  
      let createPeerConnection = () =&gt; {
          try {
              pc = new RTCPeerConnection(PC_CONFIG);
              pc.onicecandidate = onIceCandidate;
              pc.onaddstream = onAddStream;
              pc.addStream(localStream);
              console.log('PeerConnection created');
          } catch (error) {
              console.error('PeerConnection failed: ', error);
          }
      };
  
      let sendOffer = () =&gt; {
          console.log('Send offer');
          pc.createOffer().then(
              setAndSendLocalDescription,
              (error) =&gt; {
                  console.error('Send offer failed: ', error);
              }
          );
      };
  
      let sendAnswer = () =&gt; {
          console.log('Send answer');
          pc.createAnswer().then(
              setAndSendLocalDescription,
              (error) =&gt; {
                  console.error('Send answer failed: ', error);
              }
          );
      };
  
      let setAndSendLocalDescription = (sessionDescription) =&gt; {
          pc.setLocalDescription(sessionDescription);
          console.log('Local description set');
          sendData(sessionDescription);
      };
  
      let onIceCandidate = (event) =&gt; {
          if (event.candidate) {
              console.log('ICE candidate');
              sendData({
                  type: 'candidate',
                  candidate: event.candidate
              });
          }
      };
  
      let onAddStream = (event) =&gt; {
          console.log('Add stream');
          remoteStreamElement.srcObject = event.stream;
      };
  
      let handleSignalingData = (data) =&gt; {
          // let msg = JSON.parse(data);
          switch (data.type) {
              case 'offer':
                  createPeerConnection();
                  pc.setRemoteDescription(new RTCSessionDescription(data));
                  sendAnswer();
                  break;
              case 'answer':
                  pc.setRemoteDescription(new RTCSessionDescription(data));
                  break;
              case 'candidate':
                  pc.addIceCandidate(new RTCIceCandidate(data.candidate));
                  break;
          }
      };
  
      // Start connection
      getLocalStream();
  &lt;/script&gt;
  </code></pre>
  <p>Also i use this code for client as socket.io</p>
  <p><a href="https://github.com/socketio/socket.io/blob/master/client-dist/socket.io.js" rel="noreferrer">https://github.com/socketio/socket.io/blob/master/client-dist/socket.io.js</a></p>
  <p>When two people are in the connection, everything works great.
  <em>But as soon as a third user tries to connect to them, the streaming stops with an error</em></p>
  <blockquote>
  <p>Uncaught (in promise) DOMException: Failed to execute
  'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote
  answer sdp: Called in wrong state: stable</p>
  </blockquote>
  <p>I don't have much knowledge of <code>javascript</code>, so I need your help. Thanks.</p>
  <p><em>P.S. I see this error in all browsers.</em></p>
  <p>See this repository</p>
  <p><a href="https://github.com/pfertyk/webrtc-working-example" rel="noreferrer">https://github.com/pfertyk/webrtc-working-example</a></p>
  <p>See this instructions</p>
  <p><a href="https://pfertyk.me/2020/03/webrtc-a-working-example/" rel="noreferrer">https://pfertyk.me/2020/03/webrtc-a-working-example/</a></p>