jamiepine/voicebox · error · Error

Microphone access is not available. Please ensure you are us

Error message

Microphone access is not available. Please ensure you are using a secure context (HTTPS or localhost) and that your browser has microphone permissions enabled.

What it means

Thrown by `startRecording()` in `useAudioRecording.ts` (line 53-57) on the non-Tauri (browser) branch when `navigator.mediaDevices.getUserMedia` is unavailable. The message points at the secure-context requirement (HTTPS or localhost) and browser mic permissions. Selected when `platform.metadata.isTauri` is false.

Source

Thrown at app/src/lib/hooks/useAudioRecording.ts:57

      }

      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        // Try waiting a bit for Tauri webview to initialize
        await new Promise((resolve) => setTimeout(resolve, 100));

        if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
          console.error('MediaDevices check:', {
            hasNavigator: typeof navigator !== 'undefined',
            hasMediaDevices: !!navigator?.mediaDevices,
            hasGetUserMedia: !!navigator?.mediaDevices?.getUserMedia,
            isTauri: platform.metadata.isTauri,
          });

          const errorMsg = platform.metadata.isTauri
            ? 'Microphone access is not available. Please ensure:\n1. The app has microphone permissions in System Settings (macOS: System Settings > Privacy & Security > Microphone)\n2. You restart the app after granting permissions\n3. You are using Tauri v2 with a webview that supports getUserMedia'
            : 'Microphone access is not available. Please ensure you are using a secure context (HTTPS or localhost) and that your browser has microphone permissions enabled.';
          setError(errorMsg);
          throw new Error(errorMsg);
        }
      }

      // Request microphone access
      const stream = await navigator.mediaDevices.getUserMedia({
        audio: {
          echoCancellation: true,
          noiseSuppression: true,
          autoGainControl: true,
        },
      });

      streamRef.current = stream;

      // Create MediaRecorder with preferred MIME type
      const options: MediaRecorderOptions = {
        mimeType: 'audio/webm;codecs=opus',
      };

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Serve the app over HTTPS, or access it via `http://localhost` / `http://127.0.0.1` so the context is secure.
  2. Have the user re-prompt: click the address-bar mic icon and re-allow, or clear the site's permission and reload.
  3. Check `navigator.mediaDevices` existence and `window.isSecureContext` before calling, and degrade gracefully.
  4. Confirm a microphone device is present and enabled in OS settings.

Example fix

// before
await startRecording();

// after — verify secure context + capability first
if (!window.isSecureContext) {
  throw new Error('Microphone needs HTTPS or localhost (secure context).');
}
if (!navigator.mediaDevices?.getUserMedia) {
  throw new Error('This browser does not support getUserMedia.');
}
await startRecording();
Defensive patterns

Strategy: validation

Validate before calling

if (!window.isSecureContext) {
  throw new Error('Microphone needs HTTPS or localhost (secure context).');
}
if (!navigator.mediaDevices?.getUserMedia) {
  throw new Error('This browser does not support getUserMedia.');
}

Type guard

function canRecordInBrowser(): boolean {
  return typeof window !== 'undefined'
    && window.isSecureContext
    && !!navigator.mediaDevices
    && typeof navigator.mediaDevices.getUserMedia === 'function';
}

Try / catch

try {
  await startRecording();
} catch (e) {
  if (!window.isSecureContext) toast.error('Serve over HTTPS or use localhost.');
  else if (/permission/i.test((e as Error).message)) promptReAllowMic();
  else throw e;
}

Prevention

When it happens

Trigger: Page served over plain HTTP on a non-localhost host (getUserMedia is gated to secure contexts); browser has mic blocked site-wide; the device has no microphone; an old browser without `mediaDevices.getUserMedia`; permission revoked in site settings.

Common situations: Dev preview served over LAN IP on http:// (not https, not localhost) so the secure-context check fails; user previously blocked the mic on the site; corporate machine with no mic device; very old browser build.

Related errors


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/e7594460a3a149a3. Report an issue: GitHub.