Moshe
Moshe

Reputation: 521

Firebase : Unhandled error RangeError: Maximum call stack size exceeded

When trying to add new item (request) for a collection in my Firestore, Although The item is properly inserted to the collection - I'm getting an error that I can't figure.

updated

Unhandled error RangeError: Maximum call stack size exceeded at isLength (/srv/node_modules/lodash/lodash.js:11739:22) at isArrayLike (/srv/node_modules/lodash/lodash.js:11359:31) at keys (/srv/node_modules/lodash/lodash.js:13333:14) at /srv/node_modules/lodash/lodash.js:4920:21 at baseForOwn (/srv/node_modules/lodash/lodash.js:2990:24) at Function.mapValues (/srv/node_modules/lodash/lodash.js:13426:7) at encode (/srv/node_modules/firebase-functions/lib/providers/https.js:184:18) at /srv/node_modules/lodash/lodash.js:13427:38 at /srv/node_modules/lodash/lodash.js:4925:15 at baseForOwn (/srv/node_modules/lodash/lodash.js:2990:24)

HTML

<!-- new request modal -->
  <div class="new-request">
    <div class="modal">
      <h2>New request</h2>
      <form>
        <input type="text" name="request" placeholder="request...">
        <button>Add</button>
        <p class="error"></p>
      </form>
    </div>
  </div>

app.js

// add a new request
const requestForm = document.querySelector(".new-request form");
const requestModal = document.querySelector(".new-request");
requestForm.addEventListener("submit", (e) => {
  e.preventDefault();

  const addRequest = firebase.functions().httpsCallable("addRequest");
  addRequest({
    text: requestForm.request.value,
  })
  .then(() => {
    requestForm.reset();
    requestModal.classList.remove("open");
    requestForm.querySelector(".error").textContent = "";
  })
  .catch((error) => {
    requestForm.querySelector(".error").textContent = error.message;
  });
});

index.js (firebase functions) updated*

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

// auth trigger (user sign up)
exports.newUserSignup = functions.auth.user().onCreate((user) => {
  // for background triggers you must return a value/promise
  return admin.firestore().collection("users").doc(user.uid).set({
    email: user.email,
    upvotedOn: [],
  });
});

// auth trigger (user deleted)
exports.userDeleted = functions.auth.user().onDelete((user) => {
  // for background triggers you must return a value/promise
  const doc = admin.firestore().collection("users").doc(user.uid);
  return doc.delete();
});

// http callable function (adding a request)
exports.addRequest = functions.https.onCall((data, context) => {
  if (!context.auth) {
    throw new functions.https.HttpsError(
      "unauthenticated",
      "only authenticated users can add requests"
    );
  }
  if (data.text.length > 30) {
    throw new functions.https.HttpsError(
      "invalid-argument",
      "request must be no more than 30 characters long"
    );
  }
  return admin.firestore().collection("requests").add({
    text: data.text,
    upvotes: 0,
  });
});

Upvotes: 1

Views: 1131

Answers (1)

Louis Coulet
Louis Coulet

Reputation: 4641

This issue is similar to this one: https://stackoverflow.com/a/52569728/6016470
You should not directly return the Promise<DocumentReference> produced by your call to firestore as the result of your Cloud Function. This is because a DocumentReference is not intended for being sent back as it is not serializable (your error message comes from lodash failing to serialize due to circular references).

So in order to send serializable result, you should modify your functions as such:

exports.addRequest = functions.https.onCall((data, context) => {
  // ... 
  return admin.firestore().collection("requests").add({
    text: data.text,
    upvotes: 0,
  }).then(doc => {
    return doc.id;
  });
});

This way, your Cloud Function now returns a Promise<string>, so it can send back its result to your client.

Upvotes: 2

Related Questions