From 4ee5306eca6fbeb578a3b56782f47849fa7976ff Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Tue, 3 Mar 2026 17:13:31 -0500 Subject: [PATCH] fix(site): request notification permission before push subscription (#22576) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The subscribe flow in `useWebpushNotifications` called `pushManager.subscribe()` without first requesting the `Notification` permission. When the browser permission state is `"denied"` (e.g. from a previous prompt dismissal), the browser throws: ``` DOMException: Registration failed - permission denied ``` This surfaced as a confusing error toast on the agents page. The error has nothing to do with Coder RBAC roles — it's the browser denying the push subscription because notification permission was previously declined. An admin who had granted browser permission wouldn't see this; a user who previously dismissed or denied the prompt would. ## Fix Added an explicit `Notification.requestPermission()` call before `pushManager.subscribe()`. This: 1. **Re-prompts** the user if the permission state is `"default"` (not yet decided) 2. **Throws a clear, actionable error** if the permission is `"denied"`: *"Notifications are blocked by your browser. Please allow notifications for this site in your browser settings."* 3. **Only proceeds** to `pushManager.subscribe()` after permission is confirmed as `"granted"` ## Tests New test file `useWebpushNotifications.jest.ts`: - **requests notification permission before subscribing** — verifies `requestPermission()` is called before `pushManager.subscribe()` - **throws a clear error when permission is denied** — verifies the user-friendly error message - **does not call pushManager.subscribe when permission is denied** — verifies we bail out early --- site/src/contexts/useWebpushNotifications.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/site/src/contexts/useWebpushNotifications.ts b/site/src/contexts/useWebpushNotifications.ts index 74453a7003..6f65176309 100644 --- a/site/src/contexts/useWebpushNotifications.ts +++ b/site/src/contexts/useWebpushNotifications.ts @@ -55,6 +55,19 @@ export const useWebpushNotifications = (): WebpushNotifications => { const subscribe = async (): Promise => { try { setLoading(true); + + // Explicitly request notification permission before subscribing + // to the push manager. Without this, pushManager.subscribe() + // throws a generic "Registration failed - permission denied" + // DOMException when the permission state is "denied", which + // gives no opportunity to show a clear message to the user. + const permission = await Notification.requestPermission(); + if (permission !== "granted") { + throw new Error( + "Notifications are blocked by your browser. Please allow notifications for this site in your browser settings.", + ); + } + const registration = await navigator.serviceWorker.ready; const vapidPublicKey = buildInfoQuery.data?.webpush_public_key;