cjpais/Handy · warning

Failed to check Windows microphone permissions:

Error message

Failed to check Windows microphone permissions:

What it means

In the Windows branch of AccessibilityOnboarding's checkInitial, the app invokes the Tauri command behind hasWindowsMicrophoneAccess() to read the OS microphone privacy setting. If the invoke rejects, this catch logs the failure and deliberately fails open: it marks microphone as granted and auto-completes onboarding. So the message never blocks the user, but it means the real permission state was never established.

Source

Thrown at src/components/onboarding/AccessibilityOnboarding.tsx:149

          });
        }

        return;
      }

      try {
        const microphoneGranted = await hasWindowsMicrophoneAccess();

        setPermissions({
          accessibility: "granted",
          microphone: microphoneGranted ? "granted" : "needed",
        });

        if (microphoneGranted) {
          await completeOnboarding();
        }
      } catch (error) {
        console.warn("Failed to check Windows microphone permissions:", error);
        setPermissions({
          accessibility: "granted",
          microphone: "granted",
        });
        await completeOnboarding();
      }
    };

    checkInitial();
  }, [completeOnboarding, hasWindowsMicrophoneAccess, onComplete, t]);

  // Polling for permissions after user clicks a button
  const startPolling = useCallback(() => {
    if (pollingRef.current || permissionPlatform === null) return;

    pollingRef.current = setInterval(async () => {
      try {
        if (permissionPlatform === "windows") {

View on GitHub (pinned to c89b7bf389)

Solutions

  1. If it only appears in browser dev, guard with isTauri() from @tauri-apps/api/core before invoking
  2. Confirm the command appears in the tauri generate_handler! invoke_handler list for Windows builds
  3. Retry the check once after a short delay to rule out startup races before failing open
  4. Reconsider the fail-open policy: route the error to the permission step UI instead of auto-granting, so users are not silently onboarded with a broken mic

Example fix

// before
} catch (error) {
  console.warn("Failed to check Windows microphone permissions:", error);
  setPermissions({ accessibility: "granted", microphone: "granted" });
  await completeOnboarding();
}

// after
import { isTauri } from "@tauri-apps/api/core";
// ...
} catch (error) {
  if (!isTauri()) return; // browser dev: skip, do not complete onboarding
  console.warn("Failed to check Windows microphone permissions:", error);
  setPermissions((p) => ({ ...p, microphone: "needed" })); // fail visible, not open
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { isTauri } from "@tauri-apps/api/core";
if (!isTauri()) return; // browser dev: skip permission invoke entirely

Try / catch

try {
  const granted = await hasWindowsMicrophoneAccess();
  /* handle */
} catch (error) {
  console.warn("Failed to check Windows microphone permissions:", error);
  // decide policy explicitly: fail-open (current) vs fail-visible
  setPermissions((p) => ({ ...p, microphone: "needed" }));
}

Prevention

When it happens

Trigger: The invoke rejecting because the backend is not yet ready when the component mounts; the command not being registered in a stripped/dev build; the Windows privacy registry/service read erroring; or running the frontend via plain `bun run dev` in a browser where Tauri invoke always rejects.

Common situations: Iterating UI in Vite outside the Tauri shell; racing between webview load and command handler registration; Windows builds where the privacy-settings query API returns an unexpected error.

Related errors


AI-assisted analysis of cjpais/Handy@c89b7bf389 (2026-08-17). Data as JSON: /api/errors/939ee6dbe1a3a6d2. Report an issue: GitHub.