iflytek/astron-agent · error · DOMException
InvalidAccessError
InvalidAccessError
Error message
Track already exists.
What it means
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.
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.
Example fix
// before pc.addStream(localStream); // second call throws // after const alreadyAdded = localStream.getTracks().every(t => pc.getSenders().some(s => s.track === t)); if (!alreadyAdded) pc.addStream(localStream);
Defensive patterns
Strategy: try-catch
Validate before calling
const isDuplicate = stream.getTracks().every(t => pc.getSenders().some(s => s.track === t));
Try / catch
try { pc.addStream(stream); }
catch (e) {
if (e instanceof DOMException && e.name === 'InvalidAccessError') return;
throw e;
} Prevention
- Keep a published-tracks registry per peer connection
- Await teardown before republishing
- Cover Safari in the E2E test matrix
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/888b5c5b6046400c.
Report an issue: GitHub.
Appendix: source
Thrown at console/frontend/src/utils/avatar-sdk-web_3.1.2.1002/xrtc-player-BJTnVhG9.js:19323
const t = e.RTCPeerConnection.prototype.addTrack;
e.RTCPeerConnection.prototype.addTrack = function (e, i) {
if (!i) return t.apply(this, arguments);
this._shimmedLocalStreams = this._shimmedLocalStreams || {};
const r = t.apply(this, arguments);
return (
this._shimmedLocalStreams[i.id]
? -1 === this._shimmedLocalStreams[i.id].indexOf(r) &&
this._shimmedLocalStreams[i.id].push(r)
: (this._shimmedLocalStreams[i.id] = [i, r]),
r
);
};
const i = e.RTCPeerConnection.prototype.addStream;
e.RTCPeerConnection.prototype.addStream = function (e) {
((this._shimmedLocalStreams = this._shimmedLocalStreams || {}),
e.getTracks().forEach(e => {
if (this.getSenders().find(t => t.track === e))
throw new DOMException('Track already exists.', 'InvalidAccessError');
}));
const t = this.getSenders();
i.apply(this, arguments);
const r = this.getSenders().filter(e => -1 === t.indexOf(e));
this._shimmedLocalStreams[e.id] = [e].concat(r);
};
const r = e.RTCPeerConnection.prototype.removeStream;
e.RTCPeerConnection.prototype.removeStream = function (e) {
return (
(this._shimmedLocalStreams = this._shimmedLocalStreams || {}),
delete this._shimmedLocalStreams[e.id],
r.apply(this, arguments)
);
};
const n = e.RTCPeerConnection.prototype.removeTrack;
e.RTCPeerConnection.prototype.removeTrack = function (e) {
return (
(this._shimmedLocalStreams = this._shimmedLocalStreams || {}),View on GitHub (pinned to 5e758547a8)