Skip to content

getInstanceIdToken should not report messaging/token-subscribe-failed exceptions #4909

@sudkumar

Description

@sudkumar

Description

I was successfully using @firebase/functions in my application and recently added @firebase/messaging. Everything works in development environment but when pushed to staging, I am getting messaging/token-subscribe-failed error in my existing flows which were working with @firebase/functions.

It seemed like functions module is somehow accessing messaging module. After a close inspection and debugging, I found that getInstanceIdToken is calling messaging.getToken.

async getInstanceIdToken(): Promise<string | undefined> {
if (
!this.messaging ||
!('Notification' in self) ||
Notification.permission !== 'granted'
) {
return undefined;
}
try {
return this.messaging.getToken();
} catch (e) {
// We don't warn on this, because it usually means messaging isn't set up.
// console.warn('Failed to retrieve instance id token.', e);
// If there's any error when trying to get the token, leave it off.
return undefined;
}
}

I am not fully aware of the reasoning behind it but after reading the following comments

// We don't warn on this, because it usually means messaging isn't set up.

, I found an issue here. When I checked the control flow of this function. It looks like the control flow will never enter into the catch block because the return value of messaging.getToken is a pending promise.

Screenshots for Error Messages

Error Message

Console.error

Environment Configuration

  • Any Browser
  • Firebase/JS v8.2.1
  • Integrated functions and messaging services
  • Hosting on custom domains
  • Notifications Permission is "Granted"
    • Customer initially click on "Notify Me" feature of app and subscribed to notifications
    • Granted notifications permission
    • [Important] Clicked on "Notify Me" again and unsubscribed from the notifications
    • [Important] Notifications permission is still set to "granted" in the browser
    • Refresh the page before testing

Reproduce the Error

Once can directly identify this issue in getInstanceIdToken method of functions module with a simple control flow analysis.

Here are some step to reproduce this inside an application

  1. Create a firebase Web App with any starter kit.
  2. Integrate @firebase/functions module and call any httpsCallable('<your_function>') for your implementation
  3. Please test that it is working as expected
  4. Now integrate the @firebase/messaging module following this tutorial
  5. Preview the application in the web browser and grant permissions for Notifications.
  6. Now test your cloud function from step 2 (httpsCallable('<your_function>')) again. It will start throwing messaging/token-subscribe-failed. It works on your local development environment (as it was in my case), please deploy it to a custom domain (non-firebase).

Suggest a Fix

This is a minor issue with the code and can be fixed with a simple await statement before messaging.getToken call

 try { 
-   return this.messaging.getToken(); 
+   return await this.messaging.getToken();
} catch (e) { 

Here, the await will ensure that exceptions go to the catch statement.

I am happy to contribute with a PR if this qualifies as an issue.


Please let me know if you need any more information regarding this issue. Also, please direct me if I am doing some wrong here.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions