Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RangeError: Maximum call stack size exceeded #1665

Closed
BenBals opened this issue Jul 4, 2014 · 37 comments
Closed

RangeError: Maximum call stack size exceeded #1665

BenBals opened this issue Jul 4, 2014 · 37 comments

Comments

@BenBals
Copy link

BenBals commented Jul 4, 2014

I am just calling `ìo.sockets.emit('hey', data);and it will crash withRangeError: Maximum call stack size exceeded``. I use it in other places in my app and it works fine. I am not repeating this (checked with console). The logs say the error is in``socket.io/node_modules/has-binary-data/index.js:46``.

I dont know where the problem is. I tried logging io.sockets right before using it and it outputs this:


{ name: '/',
17:39:37 web.1  |   server:
17:39:37 web.1  |    { nsps: { '/': [Circular] },
17:39:37 web.1  |      _path: '/socket.io',
17:39:37 web.1  |      _serveClient: true,
17:39:37 web.1  |      _adapter: [Function: Adapter],
17:39:37 web.1  |      _origins: '*:*',
17:39:37 web.1  |      sockets: [Circular],
17:39:37 web.1  |      eio:
17:39:37 web.1  |       { clients: [Object],
17:39:37 web.1  |         clientsCount: 2,
17:39:37 web.1  |         pingTimeout: 60000,
17:39:37 web.1  |         pingInterval: 25000,
17:39:37 web.1  |         upgradeTimeout: 10000,
17:39:37 web.1  |         maxHttpBufferSize: 100000000,
17:39:37 web.1  |         transports: [Object],
17:39:37 web.1  |         allowUpgrades: true,
17:39:37 web.1  |         allowRequest: [Function],
17:39:37 web.1  |         cookie: 'io',
17:39:37 web.1  |         ws: [Object],
17:39:37 web.1  |         _events: [Object] },
17:39:37 web.1  |      engine:
17:39:37 web.1  |       { clients: [Object],
17:39:37 web.1  |         clientsCount: 2,
17:39:37 web.1  |         pingTimeout: 60000,
17:39:37 web.1  |         pingInterval: 25000,
17:39:37 web.1  |         upgradeTimeout: 10000,
17:39:37 web.1  |         maxHttpBufferSize: 100000000,
17:39:37 web.1  |         transports: [Object],
17:39:37 web.1  |         allowUpgrades: true,
17:39:37 web.1  |         allowRequest: [Function],
17:39:37 web.1  |         cookie: 'io',
17:39:37 web.1  |         ws: [Object],
17:39:37 web.1  |         _events: [Object] } },
17:39:37 web.1  |   sockets:
17:39:37 web.1  |    [ { nsp: [Circular],
17:39:37 web.1  |        server: [Object],
17:39:37 web.1  |        adapter: [Object],
17:39:37 web.1  |        id: 'RfgXeMgHeP_9SQC5AAAC',
17:39:37 web.1  |        client: [Object],
17:39:37 web.1  |        conn: [Object],
17:39:37 web.1  |        rooms: [Object],
17:39:37 web.1  |        acks: {},
17:39:37 web.1  |        connected: true,
17:39:37 web.1  |        disconnected: false,
17:39:37 web.1  |        handshake: [Object],
17:39:37 web.1  |        _events: [Object] },
17:39:37 web.1  |      { nsp: [Circular],
17:39:37 web.1  |        server: [Object],
17:39:37 web.1  |        adapter: [Object],
17:39:37 web.1  |        id: '7TEjGJjWzxObulClAAAD',
17:39:37 web.1  |        client: [Object],
17:39:37 web.1  |        conn: [Object],
17:39:37 web.1  |        rooms: [Object],
17:39:37 web.1  |        acks: {},
17:39:37 web.1  |        connected: true,
17:39:37 web.1  |        disconnected: false,
17:39:37 web.1  |        handshake: [Object],
17:39:37 web.1  |        _events: [Object] } ],
17:39:37 web.1  |   connected:
17:39:37 web.1  |    { RfgXeMgHeP_9SQC5AAAC:
17:39:37 web.1  |       { nsp: [Circular],
17:39:37 web.1  |         server: [Object],
17:39:37 web.1  |         adapter: [Object],
17:39:37 web.1  |         id: 'RfgXeMgHeP_9SQC5AAAC',
17:39:37 web.1  |         client: [Object],
17:39:37 web.1  |         conn: [Object],
17:39:37 web.1  |         rooms: [Object],
17:39:37 web.1  |         acks: {},
17:39:37 web.1  |         connected: true,
17:39:37 web.1  |         disconnected: false,
17:39:37 web.1  |         handshake: [Object],
17:39:37 web.1  |         _events: [Object] },
17:39:37 web.1  |      '7TEjGJjWzxObulClAAAD':
17:39:37 web.1  |       { nsp: [Circular],
17:39:37 web.1  |         server: [Object],
17:39:37 web.1  |         adapter: [Object],
17:39:37 web.1  |         id: '7TEjGJjWzxObulClAAAD',
17:39:37 web.1  |         client: [Object],
17:39:37 web.1  |         conn: [Object],
17:39:37 web.1  |         rooms: [Object],
17:39:37 web.1  |         acks: {},
17:39:37 web.1  |         connected: true,
17:39:37 web.1  |         disconnected: false,
17:39:37 web.1  |         handshake: [Object],
17:39:37 web.1  |         _events: [Object] } },
17:39:37 web.1  |   fns: [],
17:39:37 web.1  |   ids: 0,
17:39:37 web.1  |   acks: {},
17:39:37 web.1  |   adapter:
17:39:37 web.1  |    { nsp: [Circular],
17:39:37 web.1  |      rooms:
17:39:37 web.1  |       { '5MGPNOdO4th_dOuZAAAA': [],
17:39:37 web.1  |         '64rUhxxp--4Qk1MqAAAB': [],
17:39:37 web.1  |         RfgXeMgHeP_9SQC5AAAC: [Object],
17:39:37 web.1  |         '7TEjGJjWzxObulClAAAD': [Object] },
17:39:37 web.1  |      sids:
17:39:37 web.1  |       { RfgXeMgHeP_9SQC5AAAC: [Object],
17:39:37 web.1  |         '7TEjGJjWzxObulClAAAD': [Object] },
17:39:37 web.1  |      encoder: {} },
17:39:37 web.1  |   _events: { connection: [Function] } }

My code is:

if (game.scoreTeamTwo > game.scoreTeamOne && game.scoreTeamTwo > game.scoreTeamThree && game.scoreTeamTwo > game.scoreTeamFour) {
              game.winner = 2;
              io.sockets.emit('CTFEnd', game);
}

//It´s just looking if team 1 won the game and when it does is emits ````CTFEnd```` and all the other game data
@BenBals
Copy link
Author

BenBals commented Jul 6, 2014

Found a "solution" to my problem. I can send every single piece of data sperated, but it DOES NOT work with objects

@BenjaminHarding
Copy link

I have recently been getting that error also, the only difference being that it only occasionally happens for me. Been testing all morning and I have not been able to replicate the problem.

@BenBals
Copy link
Author

BenBals commented Jul 17, 2014

For me it was that it only wasn´t able to emit to everbody, when the obj was to big.

@SEAPUNK
Copy link

SEAPUNK commented Jul 18, 2014

@BenBals if the object is too big, then a decent workaround is to send it in form of a string i.e. run JSON.stringify() on it

@BenBals
Copy link
Author

BenBals commented Jul 19, 2014

I got another work around, but I considered that.

@rauchg
Copy link
Contributor

rauchg commented Jul 19, 2014

😢 looking into this

@LarsBV
Copy link

LarsBV commented Sep 16, 2014

has the same problem when emitting a object of type:
{success: file, content: file.content} where file.content is Buffer object, and all other properties of file is strings.

had to add the field content directly to the objects because hasBin() only checks the first level of a object. But when it then tried to send the buffer it got 'Maximum call stack exceeded'

@rossnorvell
Copy link

You can replicate this by emitting the socket object (one way at least) so (Below would be server to -> client )

socket.emit('crash', {socket:socket});

I'm curious if this has an actual fix though.

@Korri
Copy link

Korri commented Nov 15, 2014

Any update on that issue ?
EDIT: My issue was that I was trying to send recursive objects.

@arobbins
Copy link

Interestingly enough, I'm getting this same error when attempting to pass my Firebase data to the client side.

Error

node_modules/socket.io/node_modules/has-binary-data/index.js:46

for (var key in obj) {
                ^
RangeError: Maximum call stack size exceeded

Server-side

var DB = new Firebase('https://1234abcd.firebaseIO.com');
var USERS = DB.child("users");

io.sockets.on('connection', function(socket){

    socket.emit('test', {
        db: USERS
    });

});

@KangGwanwoo
Copy link

해결책을 찾습니다...

@BenBals
Copy link
Author

BenBals commented Feb 13, 2015

Sorry, but my Chinese isn't that great. Would you be so kind to translate this into English.

@rossnorvell
Copy link

Did a Google Translate & it comes out to "Find the Solution..." ... hardly worth responding to. For record, the solution is to not pass such large amount of data via socket.io ... it's a socket which was designed for quick, short responses. Break up your response or send it via ajax. Unsubscribing to this thread.

@SEAPUNK
Copy link

SEAPUNK commented Feb 14, 2015

One thing you the socket.io code could do is just asynchronously iterate the object and its properties, something like:

var props = [];
var obj = { a: 1, b:2, c: { d: 3, e: 4 } };

function next_prop(callback){
  if (!props.length){
    setTimeout(callback);
    return;
  }
  var prop = props.shift();
  //do whatever with the prop, call parse_obj on it if it's an object
  setTimeout(next_prop);
}

function parse_obj(obj, callback){
  for (var i in obj){
    props.push(i);
  }
  setTimeout(function(){next_prop(callback);});
}

parse_obj(obj);

Of course, this isn't actual code you should use, because there needs to be wrapping of functions for each individual object in case they're nested, otherwise you'll have conflicts with what object is being parsed.

@marks-chan
Copy link

I just get that error too, my code is like: "io.sockets.emit('key', data);"
i try to simplify the "data" object and keep it small, and it worked.
--AND,i look into the src code,found this:

image_20150306180547

when your "data" object has recursive attribute refering, this code would crash.
e.g. proto > proto > proto ...

@ecasilla
Copy link

+1 would the core team like a async version of of binary checking i can help get that setup

@mtrabelsi
Copy link

I can reproduce the problem by sending the socket object :)

@xenyou
Copy link

xenyou commented Feb 27, 2016

+1 IE11 shows 'out of stack space' in _hasBinary.

@kevnk
Copy link

kevnk commented Apr 27, 2016

This error showed for me when I was trying to send the whole socket object back to the client. All I really needed was socket.id so the error disappeared when I sent back a smaller item — in my case, socket.id instead of the whole socket object

@LordMajestros
Copy link

LordMajestros commented Apr 27, 2016

This probably happened because you were trying to send an object with circular references resulting in recursive calls that exceeded the stack size.

@e-m-s-y
Copy link

e-m-s-y commented May 13, 2016

@LordMajestros That fixed it for me! Thanks

@LordMajestros
Copy link

@GerbenHofman you're welcome

@shunjikonishi
Copy link

shunjikonishi commented May 13, 2016

I faced same error on NodeJS v4.4.4 and socket.io v1.4.5.

In my case, it happens after disconnect event.
And it happens only when I called socket.emit more than 200,000 times.

If the number of call socket.emit is around 100,000, this error never happen.

The parameter I use with emit is always string

Does this information helps you?

@emmerich
Copy link

emmerich commented Aug 4, 2016

Just to add to @shunjikonishi , I've seen this happen as soon as I have sent exactly 100,000 events via io.emit. I have 1 socked connected, so seems like 100,000 is a hard cap.

Seems like this is a limit imposed by Node (or the JavaScript runtime) and Socket.io is holding a reference to something every time you call emit, so when you hit the 100,000th emit it just falls over.

Tested with Node 5.11.0 and Socketio 1.4.8. My version of Node is different (as well as my operating system etc, really no idea where this 100,000 comes from) than @shunjikonishi which may explain why I hit the limit at 100,000 whereas he got up to 200,000.

I ran the exact same code using ws.js and it worked fine, surpassed 100,000 socket emits without problem, so maybe it's a problem with Socket.io.

@adamreisnz
Copy link

Is there any chance of Socket IO implementing a guard against recursive data being emitted from and failing with this error? A simple detection could prevent this error from happening and emit instead a more meaningful error, like "You may be trying to send circular data". That would make it easier to debug.

@Lukenickerson
Copy link

There are quite a few decent solutions for detecting circular data: https://stackoverflow.com/questions/14962018/detecting-and-fixing-circular-references-in-javascript

One short solution relies on JSON.stringify to find the problem:

function isObjectCircular(obj) {
    try {
        JSON.stringify(circularReference);
    } catch(err) {
        return (err.toString() === 'TypeError: Converting circular structure to JSON');
    }
    return false;
}

More details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value

@mtrabelsi
Copy link

@adamreisnz You are welcome to make a PR ;)

@adamreisnz
Copy link

adamreisnz commented May 5, 2018

It always catches me off guard when someone mentions me 5 months after I made a comment 😆

@tempest2023
Copy link

I met this error too. And that's why I waste two hours to check my whole codes :<.
I think it caused by recursion object like A={B:{C:A}}, and obviously socket is a recursion object.
In fact, I guess it happened because in buffer.js, they use a recursion to find the length of data which you want to send. And then get the "maximum call stack size exceeded". If they use JSON.stringify() to get the length, there will be another clearly error about "circular structure". By the way, it has a bad key word to google!

@dustingraham
Copy link

I just ran into this as well.

hasBin will fill the stack with a recursive loop if trying to send an object that has a circular reference.

@dustingraham
Copy link

Shucks, I see there is a PR that has been open for 2 years that would fix this:

@darrachequesne
Copy link
Member

@dustingraham the fix does look great, though I'm not sure about the performance implications.

Also, even if it doesn't throw in the hasBinary method anymore, I'm afraid the JSON.stringify method that is called later in the code will still throw an error:

> var a = {};
undefined
> var b = { a: a };
undefined
> a.b = b
{ a: { b: [Circular] } }
> JSON.stringify(a)
Thrown:
TypeError: Converting circular structure to JSON
    at JSON.stringify (<anonymous>)

@darrachequesne
Copy link
Member

For future readers: sending packet with circular references is not supported by default, since the default parser relies on JSON.stringify().

If you have such a use case, you can provide your own parser: https://socket.io/docs/v3/custom-parser/

@The-Fuse
Copy link

Anyone got any solution.
I'm also getting the same error while trying to save the socket object in an array.

@fo-nhan
Copy link

fo-nhan commented May 20, 2022

Xin lỗi, nhưng tiếng Trung của tôi không tốt lắm. Bạn có vui lòng dịch cái này sang tiếng Anh không.

He is Korean

@GlistenSTAR
Copy link

Hello, How are you?
Currently, I am implementing chat app using socket.io@4.5.1.
image
But I get this error like image.
image
What is solution and Can you help me, please?
Warm regards

@tempest2023
Copy link

Check if there is a circle json object, because when you emit an event with data which is an object, it will convert the object to string by recursion. If you transfer a circle object, it will cause endless recursion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests