title: How to set remote description for a WebRTC caller in Chrome without errors?
body: <p>I hope there is no flaw in the logic.</p>
  
  <p><strong>Step 1:</strong> caller creates offer</p>
  
  <p><strong>Step 2:</strong> caller sets localDescription</p>
  
  <p><strong>Step 3:</strong> caller sends the description to the callee</p>
  
  <p>//------------------------------------------------------//</p>
  
  <p><strong>Step 4:</strong> callee receives the offer sets remote description</p>
  
  <p><strong>Step 5:</strong> callee creates answer</p>
  
  <p><strong>Step 6:</strong> callee sets local description</p>
  
  <p><strong>Step 7:</strong> callee send the description to caller</p>
  
  <p>//------------------------------------------------------//</p>
  
  <p><strong>Step 8:</strong> caller receives the answer and sets remote description</p>
  
  <p>And here is the code for the above</p>
  
  <pre><code>const socket = io();
  const constraints = {
    audio: true,
    video: true
  };
  const configuration = {
    iceServers: [{
      "url": "stun:23.21.150.121"
    }, {
      "url": "stun:stun.l.google.com:19302"
    }]
  };
  
  const selfView = $('#selfView')[0];
  const remoteView = $('#remoteView')[0];
  
  var pc = new RTCPeerConnection(configuration);
  
  pc.onicecandidate = ({
    candidate
  }) =&gt; {
    socket.emit('message', {
      to: $('#remote').val(),
      candidate: candidate
    });
  };
  
  pc.onnegotiationneeded = async () =&gt; {
    try {
      await pc.setLocalDescription(await pc.createOffer());
      socket.emit('message', {
        to: $('#remote').val(),
        desc: pc.localDescription
      });
    } catch (err) {
      console.error(err);
    }
  };
  
  pc.ontrack = (event) =&gt; {
    // don't set srcObject again if it is already set.
    if (remoteView.srcObject) return;
    remoteView.srcObject = event.streams[0];
  };
  
  socket.on('message', async ({
    from,
    desc,
    candidate
  }) =&gt; {
    $('#remote').val(from);
    try {
      if (desc) {
        // if we get an offer, we need to reply with an answer
        if (desc.type === 'offer') {
          await pc.setRemoteDescription(desc);
          const stream = await navigator.mediaDevices.getUserMedia(constraints);
          stream.getTracks().forEach((track) =&gt; pc.addTrack(track, stream));
          selfView.srcObject = stream;
          await pc.setLocalDescription(await pc.createAnswer());
          console.log(pc.localDescription);
          socket.emit({
            to: from,
            desc: pc.localDescription
          });
        } else if (desc.type === 'answer') {
          await pc.setRemoteDescription(desc).catch(err =&gt; console.log(err));
        } else {
          console.log('Unsupported SDP type.');
        }
      } else if (candidate) {
        await pc.addIceCandidate(new RTCIceCandidate(candidate)).catch(err =&gt; console.log(err));
      }
    } catch (err) {
      console.error(err);
    }
  });
  
  
  async function start() {
    try {
      // get local stream, show it in self-view and add it to be sent
      const stream = await requestUserMedia(constraints);
      stream.getTracks().forEach((track) =&gt; pc.addTrack(track, stream));
      attachMediaStream(selfView, stream);
    } catch (err) {
      console.error(err);
    }
  }
  
  socket.on('id', (data) =&gt; {
    $('#myid').text(data.id);
  });
  
  
  // this function is called once the caller hits connect after inserting the unique id of the callee
  async function connect() {
    try {
      await pc.setLocalDescription(await pc.createOffer());
      socket.emit('message', {
        to: $('#remote').val(),
        desc: pc.localDescription
      });
    } catch (err) {
      console.error(err);
    }
  }
  
  socket.on('error', data =&gt; {
    console.log(data);
  });
  </code></pre>
  
  <p>Now this code throws an error while executing <strong>Step 8</strong></p>
  
  <blockquote>
    <p>DOMException: Failed to execute 'setRemoteDescription' on
    'RTCPeerConnection': Failed to set remote offer sdp: Called in wrong
    state: kHaveLocalOffer</p>
    
    <p>DOMException: Failed to execute 'addIceCandidate' on
    'RTCPeerConnection': Error processing ICE candidate</p>
  </blockquote>
  
  <p>Tried to debug but didn't find any flaw in the logic or code. Noticed one weird thing that the the <code>pc</code> object has <code>localDescription</code> and <code>currentLocalDescription</code> and i think the callee who creates the answer must have both the description type to be <code>answer</code> but instead shows the <code>localDescription</code> to be <code>offer</code> and <code>currentLocalDescription</code> type is <code>answer</code>.</p>
  
  <p><a href="https://i.stack.imgur.com/DIpkq.png" rel="noreferrer"><img src="https://i.stack.imgur.com/DIpkq.png" alt="enter image description here"></a>
  I have no idea if it is supposed to behave like that or not as I am begginer.</p>
  
  <p>Thanks in advance.</p>