Discord.js 13.0.0+

Bug

This is a FXServer bug that makes [email protected]+ not working properly. This can probably affect other node modules but I haven’t tested it.

FXServer: Debian 10 with 4960 artifacts.
Node.js version: 16.3.0
Discord.js version: [email protected]

How to reproduce

Create discord bot application with privileged gateway intents:

Create FXServer resource with server-side .js file. Use this code inside:

Replace guild_id and client_token with your data.

const { Client } = require('discord.js');
const client = new Client({intents: ['GUILDS', 'GUILD_MEMBERS']});

client.on('ready', async function() {
    let guild = await client.guilds.fetch('guild_id');
    let members = await guild.members.fetch();

    console.log(members);
});

client.login('client_token');

Running this code as a resource will throw this error:

Uncaught TypeError: Cannot read properties of undefined (reading 'refresh')
/home/node_modules/discord.js/src/managers/GuildMemberManager.js(417,17): handler
node:events(394,28): emit

/home/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js(31,10): module.exports

/home/node_modules/discord.js/src/client/websocket/WebSocketManager.js(350,31): handlePacket
/home/node_modules/discord.js/src/client/websocket/WebSocketShard.js(443,22): onPacket
/home/node_modules/discord.js/src/client/websocket/WebSocketShard.js(300,10): onMessage
/home/node_modules/discord.js/node_modules/ws/lib/event-target.js(199,18): onMessage
node:events(394,28): emit
/home/node_modules/discord.js/node_modules/ws/lib/websocket.js(1022,20): receiverOnMessage
node:events(394,28): emit

TypeError: Cannot read properties of undefined (reading 'refresh')

The same code outside of the FXServer will give you expected results (logs out members).

discord.js hasn’t worked with FiveM for a while, I believe tabarra has a package for it to work with txAdmin, might be a good start.

EDIT: This information is wrong

Seems to be an issue with fetch().

While waiting for this to get fixed, I found a workaround. By adding the presences intent all members will be cached. This allows us to use guild.members.cache. Just using .get() will however return undefined. If we use map like I’ve done in the example below, we get an array with all guild members.

const { Client, Intents } = require("discord.js");
const { config } = require("../config/config.js");

const { botToken, guildId } = config.discord;

const myIntents = new Intents();
myIntents.add(Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_PRESENCES, Intents.FLAGS.GUILD_MEMBERS);

const client = new Client({ intents: myIntents });

client.on("ready", () => {
    let guild = client.guilds.cache.get(guildId);
    let members = guild.members.cache.map(member => member);
        
    console.log(members);
});

client.login(botToken);

Not related to the original bug report. The issue described in the report was fixed. Update your server artifacts.

I am already running the newest server artifact. So far I’ve tested build 5134, 5123 and 5104. The error persists on all these builds with the exact same error message.

Again, your issue is not related to the original bug report. We won’t provide you any support since your messages are offtopic to this post.

Can you post said actual error message?

Sure @d-bubble . When testing OPs issue on the newest build (5134), I’m getting the same error: ‘refresh’ (NodeJS.Timeout.refresh()) is undefined in the FXServer Node.js “version” (Unsure what the correct term is). This leads to an error being thrown when i.e. using fetch() in discord.js version ^13.0.0.

Error message thrown on build 5134 using the code example OP provided:

Uncaught TypeError: Cannot read properties of undefined (reading 'refresh')
\vEssentials\node_modules\discord.js\src\managers\GuildMemberManager.js(434,17): handler
node:events(394,28): emit
\vEssentials\node_modules\discord.js\src\client\websocket\handlers\GUILD_MEMBERS_CHUNK.js(31,10): module.exports
\vEssentials\node_modules\discord.js\src\client\websocket\WebSocketManager.js(350,31): handlePacket
\vEssentials\node_modules\discord.js\src\client\websocket\WebSocketShard.js(443,22): onPacket
\vEssentials\node_modules\discord.js\src\client\websocket\WebSocketShard.js(300,10): onMessage
\vEssentials\node_modules\ws\lib\event-target.js(199,18): onMessage
node:events(394,28): emit
\vEssentials\node_modules\ws\lib\websocket.js(1098,20): receiverOnMessage
node:events(394,28): emit

TypeError: Cannot read properties of undefined (reading 'refresh')

Some of the lines are slightly different, I assume it’s due to a newer version of discord.js being utilized.

Right, this library is a bit weird and somehow tries to get setTimeout from require('node:timers') yet somehow expects it to be equal to globalThis.clearTimeout etc. which in our runtime very much is not the case.

I guess you can ask the library’s maintainers to either consistently use globalThis.setTimeout etc. or add a require for clearTimeout too, but they’ve not been very receptive to this kind of request in the past.


… though they only did this as of a commit 3 days ago: refactor: import timers, `process`, and `Buffer` from `node:` (#7157) · discordjs/dis[email protected] · GitHub

This may be an attempted fix for this issue as well, but they - for whatever reason - only partially applied that change.

I’ve posted a comment on their PR pointing that out, hopefully they’ll end up seeing it so a future release of that library won’t act up like this.

Still, .refresh is implemented on our end nowadays so I’m confused that it doesn’t fix older versions of their library.

(ah, I see: they rely on unref() returning the same timeout object as well. that one should be easy to fix!)

1 Like

The missing return this; breaking current releases of discordjs should be fixed:

Also, someone replied to that PR so maybe it’ll magically work fine no matter what in newer versions of their library. :slight_smile:

2 Likes

Thank you for the quick fix! I Really appreciate all the work you and the rest of the team puts into this project :heart:

Just tested OPs code example on build 5149 and everything works as intended now.

You cannot use stock discord.js in fivem. it may look like you can and work like you can on the surface but if you actually log the debug event from it you will see it’s very much not happy as the timeout doesn’t clear and so the bot will loop reconnecting indefinitely every 20 seconds till it’s used up all your login allowance and discord sends you a message about suspicious activity and reset’s your token on you.

How do I know this? I maintain zdiscord and spent many weeks fighting it (and yes I just tested it again with the most recent artifacts and release of discord.js and it’s still the case)

You can. If anything is making it not work, report it with a repro.

This was fixed by the same commit discussed in this topic, wasn’t it?

Doesn’t seem to be in my testing, I just made a fork of the djs repo and fixed everything to work for my needs. using this test script

let helloTimeout = null;
function setHelloTimeout(time) {
    const { setTimeout } = require("node:timers");
    if (time === -1) {
        if (helloTimeout) {
            console.log("Clearing timeout.");
            clearTimeout(helloTimeout);
            helloTimeout = null;
        }
        return;
    }
    console.log("Setting timeout for 10 seconds");
    helloTimeout = setTimeout(() => {
        console.log("Timeout wasn't canceled");
    }, 10_000);
}
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function go() {
    setHelloTimeout();
    await sleep(2000);
    setHelloTimeout(-1);
}
go();

has this happen
cmd_LVWU26lwjD

You’re hitting the same bug as with the Discord.js commit that got fixed later they haven’t fixed yet:

This should be

const { setTimeout, clearTimeout } = require("node:timers");

and not be in the function, but on top level.

However, this code doesn’t apply to any released version of ‘Discord.js’, either, as far as I can tell.

Ah you’re right that was it. The code was just me trying to replicate what they were doing for the first handshake without all the overhead. I’ve had so many issues with the stupid timeout in their heartbeat from before with unref() and everything I just thought it was never going to work natively. My fork just doesn’t use the unrefs or node:timers at all and works fine now so I’ll just stick with that for now. They’re such a pain sometimes lol
Thanks for the reply, sorry for my ignorance <3

quick update: fix: import `clear{Timeout,Interval}` from `node:timers` by kyranet · Pull Request #7269 · discordjs/discord.js · GitHub their PR is up now heh

1 Like