Troubleshooting
1. “Push notifications not supported”
- The browser must implement
PushManagerandServiceWorker. - Safari (iOS) generally requires the site to be installed to the Home Screen (PWA-style) for push in many setups.
- HTTP does not work for secure contexts except
localhostfor development. Production needs HTTPS.
2. “Notification permission denied”
- If the user chose Block, you cannot show the permission prompt again from script.
- They must re-enable notifications in browser / OS site settings.
- Best practice: explain the value (“Get a ping when someone replies”) before calling
Notification.requestPermission().
3. “Subscribe endpoint returned 401”
- Your proxy is not sending a valid
Authorization: Bearer …header to Gesher, orGESHER_API_KEY/ env binding is wrong or empty. - Confirm the same key works with
curlagainst/subscribe.
4. “Subscribe endpoint returned 403 — Subscription limit reached”
- The app has reached
max_subscribersfor its plan (or the configured cap). - Raise the cap via admin
PATCH /admin/apps/:idor upgrade the plan with Gesher ops.
5. Notifications not showing
- Service worker:
navigator.serviceWorker.getRegistrations()should list your worker; check for errors in Application → Service Workers (DevTools). - Subscription:
registration.pushManager.getSubscription()should return a non-null subscription after a successful subscribe. - Permission:
Notification.permissionshould begranted. - iOS Safari: confirm PWA / Home Screen requirements for your target version.
6. “410 Gone” (or similar) in delivery stats
- Normal. Endpoints can become invalid when the user revokes permission, clears site data, or uninstalls the app.
- Gesher removes subscriptions that return 410 or 404 from the push provider during delivery.
7. Rate limit errors (429)
POST /notifyandPOST /notify/:userIdshare the per-app notify rate limiter (after auth).- Current defaults in the worker: free
100requests per minute, starter200, pro10000; enterprise is uncapped in middleware. - Response shape:
{ "error": "Rate limit exceeded", "limit": …, "window": "1 minute" }.
VAPID key fetch failures
- If omitting
vapidPublicKeyfails, callGET /vapid-keymanually and pass thepublicKeystring intovapidPublicKeyinGesherClient. - If
/vapid-keyreturns 500, the worker’sVAPID_PUBLIC_KEYbinding is missing or empty in the deployment environment.