Kellen
Kellen

Reputation: 1032

Firebase cloud functions - Error: Reference.child failed: First argument was an invalid path

I'm trying to get push notifications to work using this tutorial: https://www.youtube.com/watch?v=z27IroVNFLI

It's obviously a bit old, but there aren't many good alternatives for Firebase web apps.

I'm getting the following error when my cloud function runs:

fcmSend

Error: Reference.child failed: First argument was an invalid path = "/fcmTokens/[object Object]". Paths must be non-empty strings and can't contain ".", "#", "$", "[", or "]" at validatePathString (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:1636:15) at validateRootPathString (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:1647:5) at Reference.child (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:13688:17) at Database.ref (/srv/node_modules/@firebase/database/dist/index.node.cjs.js:14862:48) at exports.fcmSend.functions.database.ref.onWrite (/srv/index.js:21:12) at cloudFunction (/srv/node_modules/firebase-functions/lib/cloud-functions.js:131:23) at /worker/worker.js:825:24 at at process._tickDomainCallback (internal/process/next_tick.js:229:7)

Here's by cloud function:

exports.fcmSend = functions.database
                           .ref('/model_outputs/real_estate')
                           .onWrite((change, context) => {

    const userId  = change.after.val();
    console.log(change);
    const payload = {
          notification: {
            title: "test",
            body: "test body",
            icon: "https://placeimg.com/250/250/people"
          }
        };
  
  
     admin.database()
          .ref(`/fcmTokens/${userId}`)
          .once('value')
          .then(token => token.val() )
          .then(userFcmToken => {
            return admin.messaging().sendToDevice(userFcmToken, payload)
          })
          .then(res => {
            console.log("Sent Successfully", res);
            return null;
          })
          .catch(err => {
            console.log(err);
          });
  
  });

I've seen other people post about this error, but most of them had to do when them using 's instead of s in this case: admin.database().ref(/fcmTokens/${userId})`. As you can see, I'm using ticks, so I'm not sure what's wrong here.

Here's how the data is structured in my db: enter image description here

Obviously, I chopped off the ID, but I just wanted to illustrate that it's nested immediately under /fcmTokens.

Upvotes: 0

Views: 444

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83191

It seems that there are several problems in your Cloud Function:

#1

The following line generates an error because userId is not a String.

admin.database().ref(`/fcmTokens/${userId}`)

Most probably the value of the DB node at '/model_outputs/real_estate' is an Object and therefore when you do const userId = change.after.val(); you assign an Object to userId

Update following your comment above: It seems you get undefined for userId. You need to debug and solve this problem: it has to be a string.

#2

The following promise chaining is wrong:

admin.database()
      .ref(`/fcmTokens/${userId}`)
      .once('value')
      .then(token => token.val() )  // You don't return anything here, and not a Promise
      .then(userFcmToken => {
        return admin.messaging().sendToDevice(userFcmToken, payload)
      })
      .then(res => {
        console.log("Sent Successfully", res);
        return null;
      })
      .catch(err => {
        console.log(err);
      });

It should be something along the following lines, if I correctly understand your logic and data model:

admin.database()
      .ref(`/fcmTokens/${userId}`)
      .once('value')
      .then(snapshot => { 
        const userFcmToken = snapshot.val();
        return admin.messaging().sendToDevice(userFcmToken, payload)
      })
      .then(res => {
        console.log("Sent Successfully", res);
        return null;
      })
      .catch(err => {
        console.log(err);
      });

Upvotes: 2

Related Questions