Ad

Error 500 In Firebase Functions During Like & Dislike Feature

I am currently watching a tutorial bought from udemy, and during the implementation, I encountered a problem while implementing the Like or Dislike feature.

When I make a post request to a Firebase function I get a error 500 in the console, and in the Firebase functions logs I see this error:

Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.
    at Object.validateResourcePath (/srv/node_modules/@google-cloud/firestore/build/src/path.js:403:15)
    at CollectionReference.doc (/srv/node_modules/@google-cloud/firestore/build/src/reference.js:1718:20)
    at exports.updateLikesCount.functions.https.onRequest (/srv/lib/index.js:24:44)
    at cloudFunction (/srv/node_modules/firebase-functions/lib/providers/https.js:57:9)
    at /worker/worker.js:783:7
    at /worker/worker.js:766:11
    at _combinedTickCallback (internal/process/next_tick.js:132:7)
    at process._tickDomainCallback (internal/process/next_tick.js:219:9)

Index.js file functions for firebase

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

admin.initializeApp(functions.config().firebase);


// // Start writing Firebase Functions
// // https://firebase.google.com/docs/functions/typescript


export const updateLikesCount = functions.https.onRequest((request, response) => {

    console.log(request.body);

    const eventId = request.body.eventId;
    const userId = request.body.userId;
    const state = request.body.state; //like or unlike

    // tslint:disable-next-line: no-floating-promises
    admin.firestore().collection("events").doc(eventId).get().then((data: any) => {

        let likesCount = data.data().likesCount || 0;
        let likes = data.data().likes || [];

        let updateData = {} as any;


        if (state === "like") {
            updateData["likesCount"] = ++likesCount;
            updateData[`likes.${userId}`] = true;
        }
        else {
            updateData["likesCount"] = --likesCount;
            updateData[`likes.${userId}`] = false;
        }

        admin.firestore().collection("events").doc(eventId).update(updateData).then(() => {
            response.status(200).send("Done");
        }).catch((err) => {
            response.status(err.code).send(err.message);
        })

    }).catch((err) => {
        response.status(err.code).send(err.message);
    })
})

Feed.html

<div class = "content" *ngFor="let event of events">
<ion-button (click)="like(event)">Like</ion-button>
...

Feed.page.ts

like(event) {
    let body = {
      eventId: event.id,
      userId: firebase.auth().currentUser.uid,
      state: event.data().likes && event.data().likes[firebase.auth().currentUser.uid] == true ? "unlike" : "like",
    }

    // tslint:disable-next-line: max-line-length
    this.http.post("https://us-central1-cp-eventoo.cloudfunctions.net/updateLikesCount", JSON.stringify(body), { responseType: "text" }).subscribe((data) => { //third parameter represents the response(200) in functions
      console.log(data)
    }, (error) => {
      console.error(error.status);
    })
  }

When i click like button i get Error 500, when i test with postman i get this error:

Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.
    at Object.validateResourcePath (/srv/node_modules/@google-cloud/firestore/build/src/path.js:403:15)
    at CollectionReference.doc (/srv/node_modules/@google-cloud/firestore/build/src/reference.js:1718:20)
    at exports.updateLikesCount.functions.https.onRequest (/srv/lib/index.js:24:44)
    at cloudFunction (/srv/node_modules/firebase-functions/lib/providers/https.js:57:9)
    at /worker/worker.js:783:7
    at /worker/worker.js:766:11
    at _combinedTickCallback (internal/process/next_tick.js:132:7)
    at process._tickDomainCallback (internal/process/next_tick.js:219:9)
Ad

Answer

if (!is.string(resourcePath) || resourcePath === '') {
  throw new Error(`Path must be a non-empty string.`);
}

This is the line that is failing for you, your postman raw data needs to be in JSON format. By default is set to text, it must be changed to JSON(application/json)

Also, make sure your function returns a promise

export const updateLikesCount = functions.https.onRequest((request, response) => {

    console.log(request.body);

    const eventId = request.body.eventId;
    const userId = request.body.userId;
    const state = request.body.state; //like or unlike

    return admin.firestore().collection("events").doc(eventId).get().then((data: any) => {

        let likesCount = data.data().likesCount || 0;
        let likes = data.data().likes || [];

        let updateData = {} as any;


        if (state === "like") {
            updateData["likesCount"] = ++likesCount;
            updateData[`likes.${userId}`] = true;
        }
        else {
            updateData["likesCount"] = --likesCount;
            updateData[`likes.${userId}`] = false;
        }


 return admin.firestore().collection("events").doc(`${eventId}`).update(updateData).then(() => {
            response.status(200).send("Done");
        }).catch((err) => {
            response.status(err.code).send(err.message);
        })

    }).catch((err) => {
        response.status(err.code).send(err.message);
    })
})

I added a couple of return statements for your functions knows when to be finished, also ensure the doc is using the eventId as a string.

Lastly, I dont need to JSON.stringify(body) your payload, sending the object as it is it;s perfectly fine.

Ad
source: stackoverflow.com
Ad