jamiepine/voicebox · error · Error

Microphone access is not available. Please ensure: 1. The ap

Error message

Microphone access is not available. Please ensure:
1. The app has microphone permissions in System Settings (macOS: System Settings > Privacy & Security > Microphone)
2. You restart the app after granting permissions
3. You are using Tauri v2 with a webview that supports getUserMedia

What it means

Thrown by `startRecording()` in `useAudioRecording.ts` (line 53-57) on the Tauri branch when `navigator.mediaDevices` or `getUserMedia` is still absent after a 100 ms wait. The message enumerates the macOS permission grant flow and the Tauri v2 requirement. `platform.metadata.isTauri` selects this branch.

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. Open System Settings > Privacy & Security > Microphone and enable the app, then fully quit and restart it.
  2. Verify `tauri.conf.json` / capabilities grant microphone access for Tauri v2 and that the app declares the usage description.
  3. Confirm the build is Tauri v2 with a modern WKWebView (macOS)/WebView2 (Windows).
  4. If denied permanently, reset the permission (`tccutil reset Microphone <bundle-id>` on macOS) and re-prompt.

Example fix

// before — synchronous check fails immediately
await startRecording();

// after — surface a re-prompt + retry after the user opens Settings
try { await startRecording(); }
catch (e) {
  if (/microphone/i.test(e.message)) {
    showSettingsOpenDialog(); // guide user to System Settings, then retry
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Detect the missing API early and guide the user to grant permission
if (platform.metadata.isTauri && !navigator.mediaDevices?.getUserMedia) {
  throw new Error('Microphone permission needed — grant it in System Settings and restart.');
}

Type guard

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

Try / catch

try {
  await startRecording();
} catch (e) {
  if (/microphone/i.test((e as Error).message)) {
    showOpenSystemSettingsDialog(); // then offer a Retry button
  } else throw e;
}

Prevention

When it happens

Trigger: Running inside Tauri v2 but the OS has not granted microphone permission to the app; the Tauri config (capabilities/permissions) does not allow media access; the bundled webview is older than WebView2/WKWebView and lacks `getUserMedia`; permission was granted but the app was not restarted so the webview has not picked it up.

Common situations: First run on macOS where the mic permission prompt was dismissed/denied; `tauri.conf.json` capabilities missing the media/microphone permission; using a Tauri v1 build where `isTauri` is set but getUserMedia is unsupported; permission toggled in System Settings but the app must be restarted for the webview to see it.

Related errors


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