Discord.js: <shard>.broadcastEval() when dealing with client throws error

Created on 26 Jun 2019  Â·  8Comments  Â·  Source: discordjs/discord.js

Please describe the problem you are having in as much detail as possible:
When using .broadcastEval() and client values throws error
```0|shardManager | Uncaught Promise Error:
0|shardManager | TypeError: Cannot set property message of which has only a getter
0|shardManager | at /home/holo/gaius/node_modules/discord.js/src/sharding/ShardClientUtil.js:184:19

**Include a reproducible code sample here, if possible:**
```js
const Discord = require('discord.js');
const client = new Discord.Client();
client.login('token');
client.on('ready', ()=>{
client.shard.broadcastEval(`this`) // or some other property of the client, even custom properties
})

Further details:

  • discord.js version: Master#Latest
  • Node.js version: 12.4.0
  • Operating system: Linux Ubuntu
  • Priority this issue should have – Not priority but,

This bug is really annoying when attempt to glean values for debugging or runtime client modification, so it's continued existence is problematic for more than a few people I can surmise.

  • [X] I have also tested the issue on latest master, commit hash:
    discordjs/discord.js#d7b2146c81d401d0fdefd8ec040a54dfce6067e5 // From npm list
sharding

Most helpful comment

Situation

So I did a bit of digging.

The error you receive (DOMException [DataCloneError]) suggests you are using the worker mode of the sharding manager. You did not mention which mode you use, neither did I think of the worker mode, so I tested using the default process mode.

I can indeed reproduce this using the worker mode.

Fetching Client fails with that error, which makes sense when looking at the structured clone algorithm which is being used by MessagePort#postMessage.

Cause

Client extends EventEmitter, this defines an _events property where the attached listeners are getting stored. And trying to clone those fails as per:

Error and Function objects cannot be duplicated by the structured clone algorithm; attempting to do so will throw a DATA_CLONE_ERR exception.

Solution?

I don't know if we can fix this somehow on our end.

What you could do is, is calling toJSON when fetching client, this works and yields the same result as when using the process mode.
For other custom objects of yours, you probably want to define custom serializations too (for example a toJSON method) to work around this limitation.

All 8 comments

I can't reproduce this.

What I see:
The stacktrace suggest that a shard tried to respond to the parent, but an error occured.
That error from process.send for some reason had a readonly message property.
Another thing I noticed is the rogue space between the two words of which, which seems also off.
There should be some string representation of the object in question.

I can't reproduce this.

What I see:
The stacktrace suggest that a shard tried to respond to the parent, but an error occured.
That error from process.send for some reason had a readonly message property.
Another thing I noticed is the rogue space between the two words of which, which seems also off.
There should be some string representation of the object in question.

I did a console.log() on the error in question

!eval bot.shard.broadcastEval(this)

0|shardManager  | DOMException [DataCloneError]: () => { this.parentPort.postMessage({ _ready: true }); } could not be cloned.
0|shardManager  |     at /home/holo-buckshot/Documents/Discord_Bots/Gaius-/node_modules/discord.js/src/sharding/ShardClientUtil.js:78:25
0|shardManager  |     at new Promise (<anonymous>)
0|shardManager  |     at ShardClientUtil.send (/home/holo-buckshot/Documents/Discord_Bots/Gaius-/node_modules/discord.js/src/sharding/ShardClientUtil.js:72:12)
0|shardManager  |     at ShardClientUtil._respond (/home/holo-buckshot/Documents/Discord_Bots/Gaius-/node_modules/discord.js/src/sharding/ShardClientUtil.js:183:10)
0|shardManager  |     at ShardClientUtil._handleMessage (/home/holo-buckshot/Documents/Discord_Bots/Gaius-/node_modules/discord.js/src/sharding/ShardClientUtil.js:169:14)
0|shardManager  | Uncaught Promise Error: 
0|shardManager  | TypeError: Cannot set property message of  which has only a getter
0|shardManager  |     at /home/holo-buckshot/Documents/Discord_Bots/Gaius-/node_modules/discord.js/src/sharding/ShardClientUtil.js:185:19

Here's the error at shardClientUtil 185

/**
   * Sends a message to the master process, emitting an error from the client upon failure.
   * @param {string} type Type of response to send
   * @param {*} message Message to send
   * @private
   */
  _respond(type, message) {
    this.send(message).catch(err => {
      console.log(err);
      err.message = `Error when sending ${type} response to master process: ${err.message}`; // line 185
      /**
       * Emitted when the client encounters an error.
       * @event Client#error
       * @param {Error} error The error encountered
       */
      this.client.emit(Events.ERROR, err);
    });
  }

I have uninstalled and reinstalled discord.js and this still happens. I'm not entirely sure why since I've messed with the client before.

Situation

So I did a bit of digging.

The error you receive (DOMException [DataCloneError]) suggests you are using the worker mode of the sharding manager. You did not mention which mode you use, neither did I think of the worker mode, so I tested using the default process mode.

I can indeed reproduce this using the worker mode.

Fetching Client fails with that error, which makes sense when looking at the structured clone algorithm which is being used by MessagePort#postMessage.

Cause

Client extends EventEmitter, this defines an _events property where the attached listeners are getting stored. And trying to clone those fails as per:

Error and Function objects cannot be duplicated by the structured clone algorithm; attempting to do so will throw a DATA_CLONE_ERR exception.

Solution?

I don't know if we can fix this somehow on our end.

What you could do is, is calling toJSON when fetching client, this works and yields the same result as when using the process mode.
For other custom objects of yours, you probably want to define custom serializations too (for example a toJSON method) to work around this limitation.

My bad, I completely forgot to mention i'm using worker

As for the tojson

image
(i'm not sure if this image stuff works)

It dropped quite a hilarious amount of things off the client, mostly objects but a couple collections as well, is there any reason why it drops those objects?

This looks pretty normal for a client, although you appear to have heavily modified it so I can't be sure what exactly you're talking about. That being said, the toJSON method (and the Util.flatten function that powers it) is designed to strip out non-primitive properties that cannot be coerced to a primitive, so this would behave unexpectedly if you're expecting arbitrarily deep output.

This looks pretty normal for a client, although you appear to have heavily modified it so I can't be sure what exactly you're talking about. That being said, the toJSON method (and the Util.flatten function that powers it) is designed to strip out non-primitive properties that cannot be coerced to a primitive, so this would behave unexpectedly if you're expecting arbitrarily deep output.

It seems like it will dump anything that is an object or Map but keep arrays or collections.

In this case i'm not entirely sure why a copy of the client isn't created instead, dumping all functions from it in the process.

So the Util.flatten just removes anything that isn't an array, direct value, or Collection?

That is correct, although (as I said) we do make an attempt to coerce complex values to a primitive.

I have no idea what you mean with a "copy" of the client. Deep cloning an object is pretty slow, generally useless, and wouldn't really help with making JSON-serializable data.

There isn't much in the way of additional serialization that I see being needed on the client, so I'm not entirely sure what your complaint is.

Nah, you're fine, i understand, my 'problem' has been solved my 'complaint' is that i don't see all the values that are currently attached to the client, which can sometimes help remember what their names are, I'll work on doing it myself in order to get those values that i need, thanks for your explanations and what not, i appreciate the patience and support.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

BrandonCookeDev picture BrandonCookeDev  Â·  3Comments

Alipoodle picture Alipoodle  Â·  3Comments

xCuzImPro picture xCuzImPro  Â·  3Comments

Lombra picture Lombra  Â·  3Comments

Brawaru picture Brawaru  Â·  3Comments