When restart() fails it sets this.processedTrack = opts.track — the rawMediaStreamTrack LiveKit owns as _mediaStreamTrack. LiveKit's internalStopProcessor() does this.processor.processedTrack?.stop() and then setMediaStreamTrack(this._mediaStreamTrack, true) (livekit-client 2.18.x, livekit-client.esm.mjs:19621). Since the two are now the same object, any later stopProcessor() — including the module's own teardown at lotusDenoise.ts:151, or a second setProcessor() — stops the live microphone and then re-publishes the dead track. That is the A7 "mic dead after reconnect" class of bug the processor was written to fix, reintroduced on the degrade path.
How to trigger
Force one restart() failure (e.g. device switch while the denoise assets 404, or an AudioContext sample-rate mismatch), then leave the call / re-enter, or let anything call stopProcessor(). Mic is permanently silent for the rest of the session.
Suggested fix
On the fallback path set this.processedTrack = undefined (LiveKit then falls through to _mediaStreamTrack at livekit-client.esm.mjs:19141 and 19201), and never assign LiveKit-owned tracks to processedTrack.
Filed from the September 2026 audit (branch lotus).
**Severity:** high · **Type:** bug · **Confidence:** high
**Location:** `src/lotus/lotusDenoiseProcessor.ts:181-188`, `src/lotus/lotusDenoise.ts:151`
### Problem
When `restart()` fails it sets `this.processedTrack = opts.track` — the *raw* `MediaStreamTrack` LiveKit owns as `_mediaStreamTrack`. LiveKit's `internalStopProcessor()` does `this.processor.processedTrack?.stop()` and then `setMediaStreamTrack(this._mediaStreamTrack, true)` (livekit-client 2.18.x, `livekit-client.esm.mjs:19621`). Since the two are now the same object, any later `stopProcessor()` — including the module's own teardown at `lotusDenoise.ts:151`, or a second `setProcessor()` — **stops the live microphone** and then re-publishes the dead track. That is the A7 "mic dead after reconnect" class of bug the processor was written to fix, reintroduced on the degrade path.
### How to trigger
Force one `restart()` failure (e.g. device switch while the denoise assets 404, or an `AudioContext` sample-rate mismatch), then leave the call / re-enter, or let anything call `stopProcessor()`. Mic is permanently silent for the rest of the session.
### Suggested fix
On the fallback path set `this.processedTrack = undefined` (LiveKit then falls through to `_mediaStreamTrack` at `livekit-client.esm.mjs:19141` and `19201`), and never assign LiveKit-owned tracks to `processedTrack`.
---
_Filed from the September 2026 audit (branch `lotus`)._
jared
added this to the EC fork audit 2026-09 · High milestone 2026-09-12 02:12:57 -04:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Severity: high · Type: bug · Confidence: high
Location:
src/lotus/lotusDenoiseProcessor.ts:181-188,src/lotus/lotusDenoise.ts:151Problem
When
restart()fails it setsthis.processedTrack = opts.track— the rawMediaStreamTrackLiveKit owns as_mediaStreamTrack. LiveKit'sinternalStopProcessor()doesthis.processor.processedTrack?.stop()and thensetMediaStreamTrack(this._mediaStreamTrack, true)(livekit-client 2.18.x,livekit-client.esm.mjs:19621). Since the two are now the same object, any laterstopProcessor()— including the module's own teardown atlotusDenoise.ts:151, or a secondsetProcessor()— stops the live microphone and then re-publishes the dead track. That is the A7 "mic dead after reconnect" class of bug the processor was written to fix, reintroduced on the degrade path.How to trigger
Force one
restart()failure (e.g. device switch while the denoise assets 404, or anAudioContextsample-rate mismatch), then leave the call / re-enter, or let anything callstopProcessor(). Mic is permanently silent for the rest of the session.Suggested fix
On the fallback path set
this.processedTrack = undefined(LiveKit then falls through to_mediaStreamTrackatlivekit-client.esm.mjs:19141and19201), and never assign LiveKit-owned tracks toprocessedTrack.Filed from the September 2026 audit (branch
lotus).Fixed in
936a0835, shipped in0.25.0-lotus.1(published by CI from tag v0.25.0-lotus.1) and consumed by cinny at 9a85a487.