skip to Main Content

We are having issuses using server.fetchSockets() in socket.io redis nodes. When a server call this function the others servers are throwing this exception:

C:pathnode_modulessocket.io-redisdistindex.js:212
                response = JSON.stringify({
                                ^

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Pool'
    |     property 'config' -> object with constructor 'PoolConfig'
    |     property 'connectionConfig' -> object with constructor `ConnectionConfig'
    --- property 'pool' closes the circle
    at JSON.stringify (<anonymous>)
    at RedisAdapter.onrequest (C:UserspachDocumentstrace gamingnewnodenode_modulessocket.io-redisdistindex.js:212:33)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)

and the server that is calling the function gets a timeout.

Sending and receiving events are working fine.

socket.io 4.1.1
socket.io-redis 6.1.1

Function doc link

2

Answers


  1. I believe it has something to do with the first bit of the TypeError Converting circular structure to JSON. I am new to socket.io so this is just my assumption but I think each socket instance has references to itself within its data structure. Therefore when trying to parse to json you end up in a recursive loop that the engine notices and errors out of after a while hence the location the error occurs processTicksAndRejections (node:internal/process/task_queues:94:5).

    If you log a socket instance to the console you can look through it and see that some of the sockets are valued as circular. Again this is just my gut feeling on your issue but I am curious to know if you have solved it and what the issue really was!

    Login or Signup to reply.
  2. It seems like the object you want to convert is not meant to be converted to a JSON String or in other words: JSON.stringify does not know, when it has to stop converting already seen/converted objects.

    The drawing in the beginning of the socket-help explains the structure a bit.

    Every client has a reference to the server, the server has references to all clients. So if you call JSON.stringify() on any of these objects the error occurs.

    This is just a rudimentary example how the references are set to help you understanding the error message:

    myServer = { clients: [] };
    myClient = { server: myServer };
    
    myServer.clients.push(myClient);
    /**
     * If you call now myServer.clients[0].server
     * you have the same reference as if you would call myServer.
     *
     * You could continue this to infinity and beyond
     * with addition calls to .clients[0].server
     *
     * And that's the reason why the error occurs.
     * There is no end-condition.
     */
    console.log(
      myServer
        .clients[0].server
        .clients[0].server
        .clients[0].server == myServer);

    How to avoid circular references:

    You can add a replacer-function to JSON.stringify(obj, replacer).

    const obj = {};
    obj.reference = obj;
    
    function jsonWithoutCircular(obj) {
      let list = [], replacer = (name, val) => {
        if (typeof val == "function")
          return;
        if (typeof val == "object") {
          if (!list.includes(val)) {
            if (val) // only if not null
              list.push(val);
            return val;
          } else {
            return "*** CIRCULAR REFERENCE ***";
          }
        } else {
          return val
        }
      };
      return JSON.stringify(obj, replacer)
    }
    
    try {
      JSON.stringify(obj);
    } catch(e) {
      console.error(e.message);
    }
    
    console.log(jsonWithoutCircular(obj));
    
    try {
      JSON.stringify(globalThis); // or window
    } catch(e) {
      console.error(e.message);
    }
    
    // the error that appears here is related to window.parent
    console.log(jsonWithoutCircular(window));

    Other questions that may be useful:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search