Need some help tracking a 'Maximum Call stack size exceeded' bug

All,

I get an Internal Server Error 500 when I call a method that simply returns a value. Here is the exception in the log:

Exception while invoking method 'materials.getPrice' RangeError: Maximum call stack size exceeded
    at Function.isArray (native)
   at parseObj (/bundle/bundle/programs/server/npm/node_modules/mongo-object/dist/mongo-object.js:108:19)
    at /bundle/bundle/programs/server/npm/node_modules/mongo-object/dist/mongo-object.js:137:15
    at /bundle/bundle/programs/server/npm/node_modules/lodash/lodash.js:4920:15
    at Function.forEach (/bundle/bundle/programs/server/npm/node_modules/lodash/lodash.js:9359:14)
    at parseObj (/bundle/bundle/programs/server/npm/node_modules/mongo-object/dist/mongo-object.js:133:28)
    at /bundle/bundle/programs/server/npm/node_modules/mongo-object/dist/mongo-object.js:137:15
    at /bundle/bundle/programs/server/npm/node_modules/lodash/lodash.js:4920:15
    at Function.forEach (/bundle/bundle/programs/server/npm/node_modules/lodash/lodash.js:9359:14)

There are a few related topics on this issue, and Iā€™m aware that it often points to passing a very large object, like an entire collection, as an argument. In this case, however, itā€™s fairly basic code and Iā€™ve spent about a day trying to track it out. Using CDT, the exception is thrown when I try to call ā€œmaterials.getPriceā€ in the code below:

Template.checkout.events({
    'submit form'(event) {
	event.preventDefault();
	const documentId = Session.get('checkoutDocumentId');
	const name = Materials.findOne(documentId).title;
	Meteor.call('materials.getPrice', documentId, (error, amount) => {
	    if (error) {
		console.log(error);
		swal({
		    title: "Checkout Failed!",
		    text: error.message,
		    type: "warning"
		});
	    } else { ...

documentID appears to resolve to a valid ID. So, Iā€™m not passing something large to materials.getPrice. What am I missing? Thereā€™s not much going on in the method itself. Here is that code:

export const getPrice = new ValidatedMethod({
  name: 'materials.getPrice',
  validate: new SimpleSchema({
    _id:  {type: String, regEx: SimpleSchema.RegEx.Id}
  }).validator({ clean: true, filter: false }),
  run({ _id }) {
    if (!this.userId)
    {
      throw new Meteor.Error("materials.getPrice", "Not authorized to remove material");
    }
      return Materials.findOne(_id).price * 100;
  }
});

Thanks in advance for any pointers.

I think Iā€™ve got it fixed now. First, I wrote a test method that was even simpler than the one presented here. I noticed that it caused a stack overflow when I passed in any argument at all, no matter what it was. I reread the documentation for ValidatedMethod and found that in their example they were explicit about the arguments being passed.

So my Meteor.Call now looks like this:

Meteor.call('materials.getPrice', {_id: documentId}, (error, amount) => ...

Everything now works smoothly.

2 Likes