title: How to fix InvalidStateError: Cannot add ICE candidate when there is no remote SDP
body: <p>I am creating a webRTC video chat that shows a caller all active members when initiating a call from firefox and the receiver is using chrome this error is displayed  "Uncaught (in promise) DOMException: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate". And when a call is initiated from firefox and receiver uses firefox I get two errors Invalidstate: cannot add ICE candidate when there is no remote SDP and ICE failed, add a STUN and see about:webrtc for details</p>
  
  <p>I dont  know where I am making a mistake</p>
  
  <pre><code>/ define all data here
  var usersOnline,id,currentCaller,room,caller,localUser,media,memberInfo;
  // All subscribed members.
  var users = [];
  
  
  var token = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
  // create random user id
  var userId = Math.random().toString(36).substring(2, 15);
  // create random username
  var username = token;
  // authonticating user
  var currentUser = {
      username: token,
      userId: userId
  }
  // stringify user data 
  currentUser = JSON.stringify(currentUser);
  var pusher = new Pusher('KEY', {
      authEndpoint: '../auth.php',
      auth: {
          params: JSON.parse(currentUser)
      },
      cluster: 'ap2',
      forceTLS: true
  });
  
  var state = pusher.connection.state;
  
  var channel = pusher.subscribe('presence-conference');
  
  channel.bind("pusher:subscription_succeeded", function (members) {
    console.log(members);
    id = channel.members.me.id;
    document.getElementById('mydetails').innerHTML = 'Online Now: '  + '  &amp;nbsp;( ' + (members.count - 1) +')';
    members.each(member =&gt; {
      if (member.id != channel.members.me.id) {
        users.push(member.id);
      }
    });
    renderOnline();
   });
   // Add user online
  channel.bind("pusher:member_added", member =&gt; {
    users.push(member.id);
    renderOnline();
  });
  channel.bind("pusher:member_removed", member =&gt; {
  // for remove member from list:
    var index = users.indexOf(member.id);
    users.splice(index, 1);
    if (member.id == room) {
      endCall();
    }
    renderOnline();
  });
  
  function renderOnline(){
    var list = "";
    users.forEach(function(user) {
      list +=
        `&lt;li&gt;` +
        user +//this will call user
        ` &lt;input type="button" style="float:right;"  value="Call" onclick="callUser('` +
        user +
        `')" id="makeCall" /&gt;&lt;/li&gt;`;
    });
    document.getElementById("userDetails").innerHTML = list;
  }
          //To iron over browser implementation anomalies like prefixes
      GetRTCPeerConnection();
      GetRTCSessionDescription();
      GetRTCIceCandidate();
      prepareCaller();
      function prepareCaller() {
        //Initializing a peer connection
        caller = new window.RTCPeerConnection();
        //Listen for ICE Candidates and send them to remote peers
        caller.onicecandidate = function(evt) {
          if (!evt.candidate) return;
          console.log("onicecandidate called");
          onIceCandidate(caller, evt);
        };
        //onaddstream handler to receive remote feed and show in remoteview video element
        caller.onaddstream = function(evt) {
          console.log("onaddstream called");
          if("srcObject" in document.getElementById("selfview")){
              document.getElementById("selfview").srcObject = evt.stream;
          }else{
          if (window.URL) {
            document.getElementById("remoteview").src = window.URL.createObjectURL(
              evt.stream
            );
          } else {
            document.getElementById("remoteview").src = evt.stream;
          }
        }
        };
      }
      function getCam() {
        //Get local audio/video feed and show it in selfview video element
        return navigator.mediaDevices.getUserMedia({
           audio: {
               echoCancellation: true,
               sampleSize:8
           },
           video: {
              width: 1080,
              height: 720,
              aspectRatio: { ideal: 1.777778 }
           }
        });
      }
  
      function GetRTCIceCandidate() {
        window.RTCIceCandidate =
          window.RTCIceCandidate ||
          window.webkitRTCIceCandidate ||
          window.mozRTCIceCandidate ||
          window.msRTCIceCandidate;
  
        return window.RTCIceCandidate;
      }
  
      function GetRTCPeerConnection() {
        window.RTCPeerConnection =
          window.RTCPeerConnection ||
          window.webkitRTCPeerConnection ||
          window.mozRTCPeerConnection ||
          window.msRTCPeerConnection;
        return window.RTCPeerConnection;
      }
  
      function GetRTCSessionDescription() {
        window.RTCSessionDescription =
          window.RTCSessionDescription ||
          window.webkitRTCSessionDescription ||
          window.mozRTCSessionDescription ||
          window.msRTCSessionDescription;
        return window.RTCSessionDescription;
      }
  
      //Create and send offer to remote peer on button click
      function callUser(user) {
        getCam()
          .then(stream =&gt; {
              if("srcObject" in document.getElementById("selfview")){
              document.getElementById("selfview").srcObject = stream;
          }else{
            if (window.URL) {
              document.getElementById("selfview").src = window.URL.createObjectURL(
                stream
              );
            } else {
              document.getElementById("selfview").src = stream;
            }
          }
            toggleEndCallButton();
            caller.addStream(stream);
            localUserMedia = stream;
            caller.createOffer().then(function(desc) {
              caller.setLocalDescription(new RTCSessionDescription(desc));
              channel.trigger("client-sdp", {
                sdp: desc,
                room: user,
                from: id
              });
              room = user;
            });
          })
          .catch(error =&gt; {
            console.log("an error occured", error);
          });
      }
  
      function endCall() {
        room = undefined;
        caller.close();
        for (let track of localUserMedia.getTracks()) {
          track.stop();
        }
        prepareCaller();
        toggleEndCallButton();
      }
  
      function endCurrentCall() {
        channel.trigger("client-endcall", {
          room: room
        });
  
        endCall();
      }
  
      //Send the ICE Candidate to the remote peer
      function onIceCandidate(peer, evt) {
        if (evt.candidate) {
          channel.trigger("client-candidate", {
            candidate: evt.candidate,
            room: room
          });
        }
      }
  
      function toggleEndCallButton() {
        if (document.getElementById("endCall").style.display == "block") {
          document.getElementById("endCall").style.display = "none";
        } else {
          document.getElementById("endCall").style.display = "block";
        }
      }
  
      //Listening for the candidate message from a peer sent from onicecandidate handler
      channel.bind("client-candidate", function(msg) {
        if (msg.room == room) {
          console.log("candidate received");
          caller.addIceCandidate(new RTCIceCandidate(msg.candidate));
        }
      });
  
      //Listening for Session Description Protocol message with session details from remote peer
      channel.bind("client-sdp", function(msg) {
        if (msg.room == id) {
          console.log("sdp received");
          var answer = confirm(
            "You have a call from: " + msg.from + "Would you like to answer?"
          );
          if (!answer) {
            return channel.trigger("client-reject", { room: msg.room, rejected: id });
          }
          room = msg.room;
          getCam()
            .then(stream =&gt; {
              localUserMedia = stream;
              toggleEndCallButton();
              if("srcObject" in document.getElementById("selfview")){
              document.getElementById("selfview").srcObject = stream;
          }else{
              if (window.URL) {
                document.getElementById("selfview").src = window.URL.createObjectURL(
                  stream
                );
              } else {
                document.getElementById("selfview").src = stream;
              }
            }
              caller.addStream(stream);
              var sessionDesc = new RTCSessionDescription(msg.sdp);
              caller.setRemoteDescription(sessionDesc);
              caller.createAnswer().then(function(sdp) {
                caller.setLocalDescription(new RTCSessionDescription(sdp));
                channel.trigger("client-answer", {
                  sdp: sdp,
                  room: room
                });
              });
            })
            .catch(error =&gt; {
              console.log("an error occured", error);
            });
        }
      });
  
      //Listening for answer to offer sent to remote peer
      channel.bind("client-answer", function(answer) {
        if (answer.room == room) {
          console.log("answer received");
          caller.setRemoteDescription(new RTCSessionDescription(answer.sdp));
        }
      });
  
      channel.bind("client-reject", function(answer) {
        if (answer.room == room) {
          console.log("Call declined");
          alert("call to " + answer.rejected + "was politely declined");
          endCall();
        }
      });
  
      channel.bind("client-endcall", function(answer) {
        if (answer.room == room) {
          console.log("Call Ended");
          endCall();
        }
      });
  </code></pre>
  
  <p>I EXPECTED that the video call will work don't want to use any API, help me see where I went wrong.</p>