Skip to content

Windows: desktop notifications can never be enabled — "Desktop notifications are blocked. Enable them in your system settings." #2445

Description

@opinionate

Summary

On Windows, enabling Settings → Notifications → Desktop alerts always fails with
"Desktop notifications are blocked. Enable them in your system settings." — even on a
fresh install where the OS has never been asked for permission. There is nothing to
enable in Windows Settings: the app never appears in the notifications app list because
it has never posted a toast.

Root cause is an upstream bug in tauri-plugin-notification's injected JS shim
(reported separately: tauri-apps/plugins-workspace#3512), but Buzz's permission flow
turns it into a hard dead end, and a one-line change on Buzz's side works around it.

Environment

  • Buzz Desktop 0.4.22 (Buzz_0.4.22_x64-setup_alpha-unsigned.exe), also present in main
  • Windows 11 Home 10.0.26200, WebView2 runtime (Evergreen)
  • tauri-plugin-notification 2.3.3 (per desktop/src-tauri/Cargo.lock)

Steps to reproduce

  1. Install Buzz on Windows and complete onboarding.
  2. Open Settings → Notifications and turn on Desktop alerts.

Expected: toggle turns on; a toast is shown for the next mention/DM.
Actual: toggle snaps back off with the "blocked" error. No OS permission prompt is
shown, and Buzz is absent from Windows Settings → System → Notifications.

Root cause

tauri-plugin-notification injects an init script that replaces window.Notification
with a shim. At startup the shim computes its permission state
(guest-js/init.ts):

async function isPermissionGranted(): Promise<boolean> {
  if (window.Notification.permission !== 'default' || __TEMPLATE_windows__) {
    return await Promise.resolve(window.Notification.permission === 'granted')
  }
  return await invoke('plugin:notification|is_permission_granted')
}

On Windows __TEMPLATE_windows__ is true, so this always evaluates
window.Notification.permission === 'granted' against the shim's own
freshly-initialized 'default'false → the bootstrap stamps the permission
denied on every launch, without ever consulting the backend (whose
permission_state() unconditionally returns Granted on Windows).

Buzz then hits this in desktop/src/features/notifications/lib/desktop.ts
(getDesktopNotificationPermissionState), which trusts window.Notification.permission
first, and in desktop/src/features/notifications/hooks.ts (setDesktopEnabled),
which only calls requestDesktopNotificationAccess() when the state is "default".
Since the state is already "denied", the request that would repair it is never made,
and the user is told to fix it in system settings — where there is nothing to fix.

Verification

Attached the live app via the WebView2 CDP endpoint
(WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=9222):

window.Notification.permission          → "denied"   (tauri shim, fresh launch)
window.Notification.requestPermission() → "granted"  (backend happily grants)
window.Notification.permission          → "granted"  (toggle now works, toasts fire)

So the OS and the plugin backend both allow notifications; only the shim's cached
bootstrap value is wrong.

Suggested fix (Buzz side, until upstream lands)

In setDesktopEnabled (hooks.ts), also attempt the permission request when the
reported state is "denied" on Windows — requestPermission() corrects the shim's
state and returns "granted":

if (nextPermission === "default" || (nextPermission === "denied" && isWindowsPlatform())) {
  nextPermission = await requestDesktopNotificationAccess();
  setPermission(nextPermission);
}

Alternatively, getDesktopNotificationPermissionState could prefer the plugin's
isPermissionGranted() over window.Notification.permission when running under Tauri.

Happy to send a PR for either variant.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions