Skip to content

fix(elements): stop unbounded permission retry loop in mic selector - #466

Open
ephraimduncan wants to merge 1 commit into
vercel:mainfrom
ephraimduncan:fix/mic-selector-permission-retry-loop
Open

fix(elements): stop unbounded permission retry loop in mic selector#466
ephraimduncan wants to merge 1 commit into
vercel:mainfrom
ephraimduncan:fix/mic-selector-permission-retry-loop

Conversation

@ephraimduncan

Copy link
Copy Markdown

Denying microphone permission while the MicSelector popover was open caused endless repeated permission attempts and console error spam; a denial now settles into a single stable error. The loading state was both a dependency of the permission callback and the guard of the auto-request effect, so every rejection recreated the callback and re-fired the request. The automatic request now happens in the popover's open handler instead — at most one per open — and a denial is retried only by reopening the popover or calling loadDevices() explicitly (policy documented in the component docs). One behavior nuance: a popover that is already open on first render (defaultOpen or controlled open) no longer auto-requests on mount; requests fire on actual open events.

The new regression test was verified against the previous implementation, where it fails with an unbounded getUserMedia call count, and passes with the fix (31/31 in the suite).

Denying microphone permission re-triggered getUserMedia indefinitely
while the popover stayed open: the loading state was both a callback
dependency and an effect guard, so every rejection recreated the
callback and re-fired the effect.

Replace the effect with an onOpenChange handler that makes at most one
automatic permission request per popover open. Track in-flight loads
with a ref so both loader callbacks have stable identity. Denial now
settles into a stable error; reopening or calling loadDevices is the
retry boundary.
@vercel

vercel Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

@ephraimduncan is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

});
const [width, setWidth] = useState(200);
const { devices, loading, hasPermission, loadDevices } = useAudioDevices();
const { devices, hasPermission, loadDevices } = useAudioDevices();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controlled programmatic open={true} no longer triggers microphone permission/device enumeration because loading was moved into Radix's onOpenChange, which isn't fired for controlled prop changes.

Fix on Vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant