Rare message double-sends when using @discordjs/proxy

Hi! I'm using djs/proxy since to my knowledge, it's the preferred way of handling rate limits for process-sharded bots in d.js. I'm experiencing some rare issues where join messages in my support server (likely others as well, this is just the server it's easiest for me to notice in) seem to send twice sometimes, and I'm not entirely sure why. I've added some logging and deduced the following: - Client is emitting guildMemberAdd only once, and this function is only being called once - This function contains no logic for retrying message delivery if it fails - These two messages are sent exactly 15 seconds apart from each other - Since there is a duplicate, the first message is sending successfully - discord.js is sending a second request to the proxy, I added some incoming request logging to the proxy and it confirms both requests are coming in exactly 15 seconds apart Here is my Client definition:
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildExpressions,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildModeration,
],
rest: {
...(proxyHostname
? { api: `http://${proxyHostname}:8080/api` }
: {
globalRequestsPerSecond: 49,
}),
},
partials: [Partials.GuildMember, Partials.Message, Partials.User],
makeCache: Options.cacheWithLimits({
...Options.DefaultMakeCacheSettings,
MessageManager: 0,
GuildMessageManager: 0,
}),
});
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildExpressions,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildModeration,
],
rest: {
...(proxyHostname
? { api: `http://${proxyHostname}:8080/api` }
: {
globalRequestsPerSecond: 49,
}),
},
partials: [Partials.GuildMember, Partials.Message, Partials.User],
makeCache: Options.cacheWithLimits({
...Options.DefaultMakeCacheSettings,
MessageManager: 0,
GuildMessageManager: 0,
}),
});
And my setup of proxy (this is a minimal modified version of the proxy-container on the d.js github, with request logging and made to build for arm64)
import { proxyRequests } from "@discordjs/proxy";
import { REST } from "@discordjs/rest";
import chalk from "chalk";
import { createServer } from "node:http";
import process from "node:process";

chalk.level = 1;

const globalRequestsPerSecond = parseInt(process.env.GLOBAL_REQUESTS_PER_SECOND ?? "50", 10);

const api = new REST({
globalRequestsPerSecond,
rejectOnRateLimit: () => true,
retries: 0,
});

const proxy = proxyRequests(api);

const server = createServer((req, res) => {
if (req.url)
console.log(
chalk.blue(new Date().toISOString()),
chalk.yellow(req.method),
chalk.green(req.url.replace(/^\/api(\/v\d+)?/, ""))
);
proxy(req, res);
});

server.on("error", err => {
console.error(chalk.red("Server error:"), err);
});

const port = parseInt(process.env.PORT ?? "8080", 10);

server.listen(port, () =>
console.log(`Listening on port ${port}. Global requests per second limited to ${globalRequestsPerSecond}.\n`)
);
import { proxyRequests } from "@discordjs/proxy";
import { REST } from "@discordjs/rest";
import chalk from "chalk";
import { createServer } from "node:http";
import process from "node:process";

chalk.level = 1;

const globalRequestsPerSecond = parseInt(process.env.GLOBAL_REQUESTS_PER_SECOND ?? "50", 10);

const api = new REST({
globalRequestsPerSecond,
rejectOnRateLimit: () => true,
retries: 0,
});

const proxy = proxyRequests(api);

const server = createServer((req, res) => {
if (req.url)
console.log(
chalk.blue(new Date().toISOString()),
chalk.yellow(req.method),
chalk.green(req.url.replace(/^\/api(\/v\d+)?/, ""))
);
proxy(req, res);
});

server.on("error", err => {
console.error(chalk.red("Server error:"), err);
});

const port = parseInt(process.env.PORT ?? "8080", 10);

server.listen(port, () =>
console.log(`Listening on port ${port}. Global requests per second limited to ${globalRequestsPerSecond}.\n`)
);
Like I said before, this rarely happens, it ends up not happening for several weeks and then only happens once. I have no way of predicting when it's going to happen and I'm not sure what causes it. I tried poking around in the source for proxy to see if I could spot anything that might be causing it (wouldn't be the first time haha), but alas no dice. Since it's receiving multiple requests to begin with, signs point to either a subtle mistake in my Client configuration, or perhaps a bug in d.js or djs/rest? I'm more so just curious if anyone else using /proxy has run into this problem too d.js version 14.19.3 node version 22.17 djs/proxy version 2.1.1 (latest)
No description
6 Replies
d.js toolkit
d.js toolkit6d ago
souji
souji5d ago
i've heard reports of rare double sending from various sources using various api wrappers so the current theory is that this is an upstream issue with discord *in the last 48h
Mac
Mac5d ago
Oh surely a discord issue though not 100% sure because I've had similar issues from the djs package itself I've had this happen to me even in voiceStateUpdate event where discord sends the same data twice sometimes after 30s of initial send. Not super common but I did have this like in the last 2 days
nick.
nick.OP4d ago
interesting, and yeah I’ve been observing this within the past few weeks not just a few days, that might just be a coincidence yeah that’s what I thought at first, that there might be gateway event duplication but that wasn’t it, my guildMemberAdd listener was only called once, and the timing of the second message being exactly 15 seconds apart suggests some sort of setTimeout or something being called in djs itself 👀 I wonder what’s going on here since the upstream request was successful, maybe some weird docker networking quirks, cause I’m not sure what would be wrong with how I set up the proxy
Ricky
Ricky4d ago
I don't put my Discord bot in Docker, and had this happen once a couple of days ago. Granted, I do have other stuff in Docker, but not the bot.
nick.
nick.OP5h ago
Do you have any suggestions for improvements I could make in how I debug this/see if it's something wrong at the proxy layer or the bot layer

Did you find this page helpful?