{"record":{"id":"888b5c5b6046400c","repo":"iflytek/astron-agent","slug":"invalidaccesserror-track-already-exists","errorCode":"InvalidAccessError","errorMessage":"Track already exists.","messagePattern":"Track already exists\\.","errorType":"exception","errorClass":"DOMException","httpStatus":null,"severity":"error","filePath":"console/frontend/src/utils/avatar-sdk-web_3.1.2.1002/xrtc-player-BJTnVhG9.js","lineNumber":19323,"sourceCode":"  const t = e.RTCPeerConnection.prototype.addTrack;\n  e.RTCPeerConnection.prototype.addTrack = function (e, i) {\n    if (!i) return t.apply(this, arguments);\n    this._shimmedLocalStreams = this._shimmedLocalStreams || {};\n    const r = t.apply(this, arguments);\n    return (\n      this._shimmedLocalStreams[i.id]\n        ? -1 === this._shimmedLocalStreams[i.id].indexOf(r) &&\n          this._shimmedLocalStreams[i.id].push(r)\n        : (this._shimmedLocalStreams[i.id] = [i, r]),\n      r\n    );\n  };\n  const i = e.RTCPeerConnection.prototype.addStream;\n  e.RTCPeerConnection.prototype.addStream = function (e) {\n    ((this._shimmedLocalStreams = this._shimmedLocalStreams || {}),\n      e.getTracks().forEach(e => {\n        if (this.getSenders().find(t => t.track === e))\n          throw new DOMException('Track already exists.', 'InvalidAccessError');\n      }));\n    const t = this.getSenders();\n    i.apply(this, arguments);\n    const r = this.getSenders().filter(e => -1 === t.indexOf(e));\n    this._shimmedLocalStreams[e.id] = [e].concat(r);\n  };\n  const r = e.RTCPeerConnection.prototype.removeStream;\n  e.RTCPeerConnection.prototype.removeStream = function (e) {\n    return (\n      (this._shimmedLocalStreams = this._shimmedLocalStreams || {}),\n      delete this._shimmedLocalStreams[e.id],\n      r.apply(this, arguments)\n    );\n  };\n  const n = e.RTCPeerConnection.prototype.removeTrack;\n  e.RTCPeerConnection.prototype.removeTrack = function (e) {\n    return (\n      (this._shimmedLocalStreams = this._shimmedLocalStreams || {}),","sourceCodeStart":19305,"sourceCodeEnd":19341,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/frontend/src/utils/avatar-sdk-web_3.1.2.1002/xrtc-player-BJTnVhG9.js#L19305-L19341","documentation":"This DOMException comes from adapter.js's addStream shim: before delegating to the original RTCPeerConnection.addStream, it checks every track of the passed stream against the existing senders (getSenders().find(t => t.track === e)). If any track is already attached to this peer connection, it throws 'Track already exists.' (InvalidAccessError) instead of creating a duplicate sender.","triggerScenarios":"Calling pc.addStream(mediaStream) (or an SDK wrapper that does) with a stream whose tracks were previously added to the same RTCPeerConnection — e.g. calling addStream twice with the same MediaStream, or adding getUserMedia tracks individually then adding the whole stream.","commonSituations":"Re-subscribing or reconnecting avatar playback without tearing down the previous peer connection; React/Vue hot-reload or StrictMode double-invocation of an effect that calls addStream twice; retry logic that re-adds the local stream after a renegotiation failure.","solutions":["Guard the call: only call addStream if no sender already carries the track (pc.getSenders().some(s => s.track === track)).","Reuse the existing sender via sender.replaceTrack(newTrack) instead of adding the stream again.","Create a fresh RTCPeerConnection (and close the old one) on reconnect instead of reusing a connection that already has the tracks.","If the SDK internally re-adds the stream, reset the SDK/player session (stop/close then recreate) before retrying."],"exampleFix":"// before\npc.addStream(localStream); // second call throws\n// after\nconst alreadyAdded = localStream.getTracks().every(t =>\n  pc.getSenders().some(s => s.track === t));\nif (!alreadyAdded) pc.addStream(localStream);","handlingStrategy":"try-catch","validationCode":"const isDuplicate = stream.getTracks().every(t => pc.getSenders().some(s => s.track === t));","typeGuard":null,"tryCatchPattern":"try { pc.addStream(stream); }\ncatch (e) {\n  if (e instanceof DOMException && e.name === 'InvalidAccessError') return;\n  throw e;\n}","preventionTips":["Keep a published-tracks registry per peer connection","Await teardown before republishing","Cover Safari in the E2E test matrix"],"tags":["webrtc","adapter-js","duplicate-track","peerconnection"],"backgroundTag":"invalid-argument-value","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}