different-ai/openwork · error

macOS denied microphone access. Enable OpenWork in System Se

Error message

macOS denied microphone access. Enable OpenWork in System Settings > Privacy & Security > Microphone, then restart OpenWork.

What it means

On macOS the panel first calls requestMacMicrophoneAccess() to trigger the OS microphone permission prompt. If macOS denies the permission (user clicked Den, or the app is blocked at the OS level), getUserMedia would fail anyway, so the panel throws with instructions pointing at System Settings.

Source

Thrown at apps/app/src/react-app/domains/session/voice/voice-panel.tsx:496

    }
  }, [addEntry, props.sessionId, requestRealtimeResponse, setRuntimeStatus]);

  const connectRealtime = useCallback(async (audioInput = true) => {
    const client = props.client;
    if (!client) throw new Error("OpenWork host connection is not ready.");
    if (audioInput && !navigator.mediaDevices?.getUserMedia) throw new Error("Microphone capture is unavailable in this runtime.");

    disconnectRealtime(true);
    setRuntimeStatus("connecting", "Minting Realtime session...");
    const sessionContext = await loadVoiceSessionContext(props.opencodeBaseUrl, props.openworkToken, props.sessionId);
    const realtimeSession = await client.createVoiceRealtimeSession({ sessionContext });

    const peer = new RTCPeerConnection();
    voiceRealtime.peer = peer;
    if (audioInput) {
      setRuntimeStatus("connecting", "Requesting microphone...");
      const macPermissionGranted = await requestMacMicrophoneAccess();
      if (!macPermissionGranted) throw new Error("macOS denied microphone access. Enable OpenWork in System Settings > Privacy & Security > Microphone, then restart OpenWork.");
      const stream = await navigator.mediaDevices.getUserMedia({
        audio: { echoCancellation: true, noiseSuppression: true, autoGainControl: true },
      });
      voiceRealtime.stream = stream;
      setMicDiagnostics(stream);
      for (const track of stream.getAudioTracks()) {
        track.addEventListener("mute", () => setMicDiagnostics(stream));
        track.addEventListener("unmute", () => setMicDiagnostics(stream));
        track.addEventListener("ended", () => setMicDiagnostics(stream));
        peer.addTrack(track, stream);
      }
    } else {
      setVoiceRuntimeSnapshot((current) => ({ ...current, micDiagnostics: "Voice command is using typed or injected audio, not the microphone." }));
      peer.addTransceiver("audio", { direction: "recvonly" });
    }

    const audio = document.createElement("audio");
    audio.autoplay = true;

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Grant OpenWork microphone access in System Settings > Privacy & Security > Microphone, then restart the app
  2. Re-trigger the permission prompt (requestMacMicrophoneAccess) and accept it
  3. Verify the packaged app has NSSMicrophoneUsageDescription and the mic entitlement — rebuild/re-sign if missing
  4. Fall back to audioInput = false (typed voice commands) until permission is granted

Example fix

// before
await connectRealtime(true);
// after
try {
  await connectRealtime(true);
} catch (e) {
  if (String(e).includes("macOS denied microphone access")) {
    toast.error("Enable OpenWork in System Settings > Privacy & Security > Microphone, then retry.");
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

const granted = await requestMacMicrophoneAccess();
if (!granted) {
  showMacMicSetupDialog();
  return;
}

Try / catch

try {
  await connectRealtime(true);
} catch (e) {
  if (e instanceof Error && e.message.includes("System Settings > Privacy & Security > Microphone")) {
    toast.error("Grant OpenWork microphone access in System Settings, then restart the app.");
  } else throw e;
}

Prevention

When it happens

Trigger: requestMacMicrophoneAccess() resolves false — the OS-level microphone permission for OpenWork is denied or undetermined-and-dismissed — while connecting with audio input on macOS.

Common situations: User previously denied the macOS mic prompt; the packaged app lacks the microphone entitlement / Info.plist NSSMicrophoneUsageDescription so the OS silently denies; enterprise MDM blocking mic access; permission reset via System Settings after an update.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/a3163cc2953f3825. Report an issue: GitHub.