19
votes

I am new to Node.js and I'm facing an error :

RangeError: Maximum call stack size exceeded

I'm not able able to solve the problem because most of the stack problems in others stackoverflow questions about Node.js deals with hundreds of callback but I have only 3 here.

First a fetch (findById) then an update an later a save operation!

My code is :

app.post('/poker/tables/:id/join', function(req, res) {
    var id = req.params.id;

    models.Table.findById(id, function(err, table) {
        if (err) {
            console.log(err);
            res.send({
                message: 'error'
            });
            return;
        }

        if (table.players.length >= table.maxPlayers) {
            res.send({
                message: "error: Can't join ! the Table is full"
            });
            return;
        }
        console.log('Table isnt Full');

        var BuyIn = table.minBuyIn;
        if (req.user.money < table.maxPlayers) {
            res.send({
                message: "error: Can't join ! Tou have not enough money"
            });
            return;
        }
        console.log('User has enought money');

        models.User.update({
            _id: req.user._id
        }, {
            $inc: {
                money: -BuyIn
            }
        }, function(err, numAffected) {
            if (err) {
                console.log(err);
                res.send({
                    message: 'error: Cant update your account'
                });
                return;
            }
            console.log('User money updated');

            table.players.push({
                userId: req.user._id,
                username: req.user.username,
                chips: BuyIn,
                cards: {}
            });

            table.save(function(err) {
                if (err) {
                    console.log(err);
                    res.send({
                        message: 'error'
                    });
                    return;
                }

                console.log('Table Successfully saved with new player!');
                res.send({
                    message: 'success',
                    table: table
                });

            });
        });

    });
});

The error occurs during the save operation at the end!

I use MongoDb with mongoose so Table and User are my database collections.

This is from my first project with Node.js,Express.js and MongoDB so I probably have made huge mistakes in the async code :(

EDIT: I tried to replace the save with an update:

models.Table.update({
    _id: table._id
}, {
    '$push': {
        players: {
            userId: req.user._id,
            username: req.user.username,
            chips: BuyIn,
            cards: {}
        }
    }
}, function(err, numAffected) {

    if (err) {
        console.log(err);
        res.send({
            message: 'error'
        });
        return;
    }

    console.log('Table Successfully saved with new player!');
    res.send({
        message: 'success',
        table: table
    });

});

But it doesn't help the error is still coming and I don't know how to debug it :/

4
Please place your answer in the answer section.casperOne
Not that it would cause a stack size issue, but this line sure looks wrong: if(req.user.money < table.maxPlayers). Nothing else sticks out as wrong about what you're doing.JohnnyHK
do you get that error after making several requests or does it occur after the first request?c0deNinja

4 Answers

22
votes

I've been passing for this problem too. Basically, when you have a property with a ref, and you want to use it in a find, for example, you can't pass the whole document.

For example:

Model.find().where( "property", OtherModelInstance );

this will trigger that error.

However, you have 2 ways to fix this for now:

Model.find().where( "property", OtherModelInstance._id );
// or
Model.find().where( "property", OtherModelInstance.toObject() );

This may stop your problems for now.

There is a issue in their GitHub repo where I reported this, however it's without fix for now. See the issue here.

5
votes

I kept getting this error and finally figured it out. It's very hard to debug since no real information is presented in the error.

Turns out I was trying to save an object into a field. Saving only a specific property of the object, or JSON stringifying it, worked like a charm.

Seems like it would be nice if the driver gave a more specific error, but oh well.

4
votes

MyModel.collection.insert causes:

[RangeError: Maximum call stack size exceeded]

When you pass array of instances of MyModel instead of just array with values of that objects.

RangeError:

let myArray = [];

myArray.push( new MyModel({ prop1: true, prop2: false }) );

MyModel.collection.insert(myArray, callback);

No error:

let myArray = [];

myArray.push( { prop1: true, prop2: false } );

MyModel.collection.insert(myArray, callback);
3
votes

There are a few ways to debug nodejs applications

Built-in Debugger

The Node.js debugger is documented here: http://nodejs.org/api/debugger.html

To place breakpoints, simply put debugger; at the place you want to break. As you said the table.save callback is giving you troubles, you could put a breakpoint inside that function.

Then you run node with the debugger enabled:

node debug myscript.js

And you will get more helpful output.

Investigating the stack

You can also use console.trace to print a stacktrace, if you have a good idea of when/where you run into problems, and want to figure out how you got there.

Good luck, I hope this helps!