Open 2manoj1 opened 1 year ago
@dyabol I'm using Flutter. I translated your code, but there still are (very rare) situations where this code ends up with a 'no service worker' issue:
Future<bool> waitServiceWorker() async { final swr = await web.window.navigator.serviceWorker.getRegistration().toDart; if (swr == null) { return false; } web.ServiceWorker? sw; if (swr!.installing != null) { sw = swr!.installing; } else if (swr!.waiting != null) { sw = swr!.waiting; } else if (swr!.active != null) { sw = swr!.active; } if (sw != null) { if (sw.state == 'activated') { return true; } var completer = Completer<bool>(); sw.onstatechange.add((web.Event e) { if ((e.target as web.ServiceWorker).state == 'activated') { completer.complete(true); } }.toJS); await completer.future; await web.window.navigator.serviceWorker.ready.toDart; return true; } return false; }
Can't be a problem in this line?
final swr = await web.window.navigator.serviceWorker.getRegistration()
In my code, I pass the ServiceWorkerRegistration instance obtained during registration. See https://github.com/firebase/firebase-js-sdk/issues/7693#issuecomment-2331302269
In my code, I pass the ServiceWorkerRegistration instance obtained during registration. See #7693 (comment)
Are you getting different references? I'd be surprised if you are.
Flutter's Firebase implementation (Flutterfire) does not let me easily dig into the registration process.
Here is one typical log output, where it succeeds after the first attempt:
Obtaining FCM token
Service worker registration is in active state
Service worker is in activated state
awaiting .ready
Calling instance.getToken, attempt #0
getToken attempt succeeded after 118826 milliseconds
FCM token obtained after 1 attempt(s)
I'll post another log once I can reproduce our present issue - which is rare.
(Note the 118 seconds delay I got here, but that's another issue. In most cases, getToken completes in under 3 seconds. Out of the maybe 1000+ (or is it 3000+) debug sessions I launched since I started to work on this project, I didn't get a delay a single time with the same Flutter code running on Android or iOS. The problem might of course come from the Flutter bridge ; or even my setup, but that's more unlikely).
@dyabol I confirm your method is not bullet proof. Just got the error this morning:
Obtaining FCM token
Service worker registration is in active state
Service worker is in activated state
Calling instance.getToken, attempt #0
getToken attempt failed after 481 milliseconds
Calling instance.getToken, attempt #1
getToken attempt failed after 1 milliseconds
Calling instance.getToken, attempt #2
getToken attempt failed after 1 milliseconds
Calling instance.getToken, attempt #3
getToken attempt failed after 12 milliseconds
Calling instance.getToken, attempt #4
getToken attempt succeeded after 3608 milliseconds
FCM token obtained after 5 attempt(s)
I am trying another attempt every time the 'no active service worker' error (and no other error) is raised.
Does anyone know what causes this? I have had firebase messaging working on many websites for several years, and I've just noticed this issue is now happening?
Make sure you are not using a truncated FCM_VAPID_KEY. Try to delete and regenerate a new one.
I had a middleware to override my fetch calls to add tenantid querystring to the url. Which was causing firebaseinstallations and fcmregistrations api calls to google fail. Skipping it fixed the issue.
I faced a similar issue, where errors occurred during the process. However, I noticed that when the page was refreshed after the error, the device token was successfully received. Based on this observation, I implemented the following logic:
I handled the issue by allowing up to 3 retry attempts when an error occurred during the request. This approach helped resolve the problem quickly after the initial error.
// Wait for the service worker registration to complete
await registerServiceWorker();
const token = await retryGetDeviceToken(3); // Retry up to 3 times
// Added retry logic for getDeviceToken
async function retryGetDeviceToken(retries: number): Promise<string> {
try {
return await getDeviceToken();
} catch (error) {
if (retries === 0) {
console.error("Maximum retry attempts exceeded:", error);
throw error;
} else {
console.warn(`Retrying getDeviceToken... Remaining attempts: ${retries}`);
return retryGetDeviceToken(retries - 1);
}
}
}
If any wonders on how to reproduce the error on Mac (Safari):
click on your website
=> RemoveI have the same issue and I registered service worker manually in NextJs. First I have register SW in useEffect:
useEffect(() => {
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("/firebase-messaging-sw.js")
.then((registration) => {
console.log("Service Worker registered successfully:", registration);
})
.catch((err) => {
console.error("Service Worker registration failed:", err);
});
}
}, []);
Then get this register SW and pass it into getToken method:
const registration = await navigator.serviceWorker.ready;
const currentToken = await getToken(messaging, {
vapidKey:
"BE6JlZIdIQYTgovJ-AAb6jbCh0TNb47ibbLcOdGiXXmToXtK46_zfRK_mLGXAkLMUHfUnbAnQ4wWlZROs_hBIH4",
serviceWorkerRegistration: registration,
});
Done it.
Hi @baigsapp,
Could you log the registration
object returned in const registration = await navigator.serviceWorker.ready;
?
Done it.
Could you clarify this? Thanks!
@DellaBitta Yes, of course. Below the log of registration
object.
Service Worker registered successfully:
ServiceWorkerRegistration {
installing: null, waiting: null, active: ServiceWorker, navigationPreload: NavigationPreloadManager, scope: 'http://localhost:3000/', …}
active: ServiceWorker {scriptURL: 'http://localhost:3000/firebase-messaging-sw.js', state: 'activated', onstatechange: null, onerror: null}
backgroundFetch: BackgroundFetchManager {}
cookies: CookieStoreManager {}
installing: null
navigationPreload: NavigationPreloadManager {}
onupdatefound: null
paymentManager: PaymentManager {userHint: ''}
periodicSync: PeriodicSyncManager {}
pushManager: PushManager {}
scope: "http://localhost:3000/"
sync: SyncManager {}
updateViaCache: "imports"
waiting: null
[[Prototype]]: ServiceWorkerRegistration
Operating System
MacOS
Browser Version
All browser
Firebase SDK Version
10.2.0
Firebase SDK Product:
Messaging
Describe your project's tooling
Nextjs 13 with Page setup. Example Repo -> https://github.com/2manoj1/nextjs-firebase-example/tree/main
Describe the problem
Same problem as https://github.com/firebase/firebase-js-sdk/issues/5797 Sometimes calling messaging getToken returns the error: Failed to execute 'subscribe' on 'PushManager': Subscription failed - no active Service Worker. It seems to occur on the first page load and clear storage with unregister sw, when the user refreshes the notifications work and there's no error anymore.
Steps and code to reproduce issue