Not recieving heartbeats, killed after ~50 seconds, zombie connection, do recieve guildCreate event

Hey, I'm having a really annoying issue. I have a ubuntu server on a digitalocean droplet where I try to host a djs 14 bot made with typescript. I have ran a djs 13 bot with javascript on the same server, with no issues. For some reason, when I run it, the bot status changes to "Online" but I never recieve the ready event, nor recieve commands. After about 50 seconds, it's killed (maybe after recieving all ~650 guilds?). This is the output from client.on("debug"):
Preparing to connect to the gateway...
[WS => Manager] Fetched Gateway Information
URL: wss://gateway.discord.gg
Recommended Shards: 1
[WS => Manager] Session Limit Information
Total: 1000
Remaining: 998
[WS => Shard 0] Connecting to wss://gateway.discord.gg?v=10&encoding=json
[WS => Shard 0] Waiting for event hello for 60000ms
[WS => Shard 0] Preparing first heartbeat of the connection with a jitter of 0.3886729184365818; waiting 16032ms
[WS => Shard 0] Waiting for identify throttle
[WS => Shard 0] Identifying
shard id: 0
shard count: 1
intents: 1
compression: none
[WS => Shard 0] Waiting for event ready for 15000ms
[WS => Shard 0] First heartbeat sent, starting to beat every 41250ms
[WS => Shard 0] Destroying shard
Reason: Zombie connection
Code: 4200
Recover: Resume
[WS => Shard 0] Connection status during destroy
Needs closing: true
Ready state: 1
Killed
Preparing to connect to the gateway...
[WS => Manager] Fetched Gateway Information
URL: wss://gateway.discord.gg
Recommended Shards: 1
[WS => Manager] Session Limit Information
Total: 1000
Remaining: 998
[WS => Shard 0] Connecting to wss://gateway.discord.gg?v=10&encoding=json
[WS => Shard 0] Waiting for event hello for 60000ms
[WS => Shard 0] Preparing first heartbeat of the connection with a jitter of 0.3886729184365818; waiting 16032ms
[WS => Shard 0] Waiting for identify throttle
[WS => Shard 0] Identifying
shard id: 0
shard count: 1
intents: 1
compression: none
[WS => Shard 0] Waiting for event ready for 15000ms
[WS => Shard 0] First heartbeat sent, starting to beat every 41250ms
[WS => Shard 0] Destroying shard
Reason: Zombie connection
Code: 4200
Recover: Resume
[WS => Shard 0] Connection status during destroy
Needs closing: true
Ready state: 1
Killed
It takes about 40-50 seconds from the "First heartbeat sent" until "Destroying shard". Using the raw event I got a lot of my guilds logged, not sure if i recieved every guild. Node version: 20.3.1 Djs: 14.11.0 Ubuntu 22.10 Please let me know if any more info is needed šŸ™‚
10 Replies
d.js toolkit
d.js toolkitā€¢12mo ago
ā€¢ What's your exact discord.js npm list discord.js and node node -v version? ā€¢ Post the full error stack trace, not just the top part! ā€¢ Show your code! ā€¢ Explain what exactly your issue is. ā€¢ Not a discord.js issue? Check out #useful-servers.
SpicyJungle
SpicyJungleā€¢12mo ago
As in I recieve a ready event? Nope Only intent I add is GatewayIntentBits.Guilds Let me try I can try that in a sec
SpicyJungle
SpicyJungleā€¢12mo ago
SpicyJungle
SpicyJungleā€¢12mo ago
Forgot to change "debug" to "raw" my b
SpicyJungle
SpicyJungleā€¢12mo ago
SpicyJungle
SpicyJungleā€¢12mo ago
it's counting guilds rn. at 217 nothing else It started off really fast and then slowed down, stuck at 219 for about 15 seconds or so got to 222 then killed Weird it didn't even send the destroying connection zombie thing this time I added it again afterwards trying a different token now
SpicyJungle
SpicyJungleā€¢12mo ago
Logged in instantly
SpicyJungle
SpicyJungleā€¢12mo ago
Yes, same bot And it takes only about 3 secs to ready from i enter the command yup beofre or after client.login? [ 'shardDisconnect', 'ready', 'interactionCreate' ] very lame, just []
wikibot3@1.0.0 /root/wikibot3
ā””ā”€ā”¬ discord.js@14.11.0
ā”œā”€ā”¬ @discordjs/ws@0.8.3
ā”‚ ā””ā”€ā”€ ws@8.13.0 deduped
ā””ā”€ā”€ ws@8.13.0
wikibot3@1.0.0 /root/wikibot3
ā””ā”€ā”¬ discord.js@14.11.0
ā”œā”€ā”¬ @discordjs/ws@0.8.3
ā”‚ ā””ā”€ā”€ ws@8.13.0 deduped
ā””ā”€ā”€ ws@8.13.0
hmm This is all
"dependencies": {
"axios": "^1.4.0",
"cheerio": "^1.0.0-rc.12",
"discord.js": "^14.11.0",
"dotenv": "^16.3.1",
"fast-average-color-node": "^2.6.0",
"typescript": "^5.1.3"
}
"dependencies": {
"axios": "^1.4.0",
"cheerio": "^1.0.0-rc.12",
"discord.js": "^14.11.0",
"dotenv": "^16.3.1",
"fast-average-color-node": "^2.6.0",
"typescript": "^5.1.3"
}
This is the entirety of the entry point:
import { Client, ClientOptions, GatewayIntentBits } from "discord.js";
import { config } from "dotenv";
config();
const clientOptions: ClientOptions = {
intents: [
GatewayIntentBits.Guilds,
],
};
const client = new Client(clientOptions);

import { Listeners } from "./Listeners";
for (const listener of Listeners) {
console.log(listener.name)
if (listener.once) {
client.once(listener.name, (...args) => listener.run(client, ...args));
} else {
client.on(listener.name, (...args) => listener.run(client, ...args));
}
}

//let guildCounter = 0;
//client
// .on("raw", (data)=>{
//if (data.t && data.t !== 'GUILD_CREATE') {
//console.log(data)
//} else {
//guildCounter = guildCounter +1
//console.log(guildCounter)
//}
//})
// .on("warn", console.log)
// .on("debug", console.log)
setTimeout(() => console.log(, 1000)
client.login(process.env.DISCORD_TOKEN);
import { Client, ClientOptions, GatewayIntentBits } from "discord.js";
import { config } from "dotenv";
config();
const clientOptions: ClientOptions = {
intents: [
GatewayIntentBits.Guilds,
],
};
const client = new Client(clientOptions);

import { Listeners } from "./Listeners";
for (const listener of Listeners) {
console.log(listener.name)
if (listener.once) {
client.once(listener.name, (...args) => listener.run(client, ...args));
} else {
client.on(listener.name, (...args) => listener.run(client, ...args));
}
}

//let guildCounter = 0;
//client
// .on("raw", (data)=>{
//if (data.t && data.t !== 'GUILD_CREATE') {
//console.log(data)
//} else {
//guildCounter = guildCounter +1
//console.log(guildCounter)
//}
//})
// .on("warn", console.log)
// .on("debug", console.log)
setTimeout(() => console.log(, 1000)
client.login(process.env.DISCORD_TOKEN);
Correct. Only those two. InteractionCreate.ts
import { Listener } from "../utils/types/Listener"
import { Commands } from "../Commands"
import { Client, ActivityType, ChatInputCommandInteraction, GuildMember, BaseInteraction } from "discord.js"
import { Command } from "../utils/types/Command";

const checkPermissions = (command: Command, member: GuildMember) => {
for (const permission of command.permissions) {
if (!member.permissions.has(permission)) return false;
}
return true;
}

export const InteractionCreate: Listener = {
name: "interactionCreate",
once: false,
run: async (client: Client, interaction: BaseInteraction) => {
console.log(`Recieved interaction: ${interaction.type}`);

if (!(interaction.isCommand()) && !(interaction.isAutocomplete())) return;

const command: Command | undefined = Commands.find(command => command.name === interaction.commandName);
if (!command) return console.log(`Command ${interaction.commandName} not found`);
if (interaction.isAutocomplete()) {
if (!command.autocomplete) return;

try {
await command.autocomplete(client, interaction);
} catch (error) {
console.error(error);
}
return;
}
if (!checkPermissions(command, interaction.member as GuildMember)) return interaction.reply({ content: "You do not have permission to use this command!", ephemeral: true });
if (command.defer) await interaction.deferReply();
try {
await command.run(client, interaction);
} catch (error) {
console.error(error);
await interaction.followUp({ content: "There was an error while executing this command!", ephemeral: true });
}
}
}
import { Listener } from "../utils/types/Listener"
import { Commands } from "../Commands"
import { Client, ActivityType, ChatInputCommandInteraction, GuildMember, BaseInteraction } from "discord.js"
import { Command } from "../utils/types/Command";

const checkPermissions = (command: Command, member: GuildMember) => {
for (const permission of command.permissions) {
if (!member.permissions.has(permission)) return false;
}
return true;
}

export const InteractionCreate: Listener = {
name: "interactionCreate",
once: false,
run: async (client: Client, interaction: BaseInteraction) => {
console.log(`Recieved interaction: ${interaction.type}`);

if (!(interaction.isCommand()) && !(interaction.isAutocomplete())) return;

const command: Command | undefined = Commands.find(command => command.name === interaction.commandName);
if (!command) return console.log(`Command ${interaction.commandName} not found`);
if (interaction.isAutocomplete()) {
if (!command.autocomplete) return;

try {
await command.autocomplete(client, interaction);
} catch (error) {
console.error(error);
}
return;
}
if (!checkPermissions(command, interaction.member as GuildMember)) return interaction.reply({ content: "You do not have permission to use this command!", ephemeral: true });
if (command.defer) await interaction.deferReply();
try {
await command.run(client, interaction);
} catch (error) {
console.error(error);
await interaction.followUp({ content: "There was an error while executing this command!", ephemeral: true });
}
}
}
Ready.ts
import { Listener } from "../utils/types/Listener"
import { Commands } from "../Commands"
import { Client, ActivityType, Guild } from "discord.js"

export const Ready: Listener = {
name: "ready",
once: true,
run: async (client: Client) => {
console.log(`Logged in as ${client.user?.tag}!`);
if (!client.user || !client.application) return console.log("Client user or application is undefined");
await client.application.commands.set(Commands);
}
}
import { Listener } from "../utils/types/Listener"
import { Commands } from "../Commands"
import { Client, ActivityType, Guild } from "discord.js"

export const Ready: Listener = {
name: "ready",
once: true,
run: async (client: Client) => {
console.log(`Logged in as ${client.user?.tag}!`);
if (!client.user || !client.application) return console.log("Client user or application is undefined");
await client.application.commands.set(Commands);
}
}
Nope, just importing the listeners and exporting them as an array ts-node Bot.ts Yup. Never done that before, do I just run tsc at the top level of the directory? well my tsConfig is only this so doubt it
{
"compilerOptions": {
"lib": ["ES2021"],
}
}
{
"compilerOptions": {
"lib": ["ES2021"],
}
}
ok
SpicyJungle
SpicyJungleā€¢12mo ago
Well. Maybe i just should upgrade the droplet and see if that solves it
SpicyJungle
SpicyJungleā€¢12mo ago
probably why the javascript bot works yeah True, I didn't expect the transpiling to take this much computing. I'll give that a shot and if not i'll just upgrade Can I transpile the JS to a completely different directory, completely seperate from the typescript? Transpiled JS ran in just a few seconds and works perfectly, thanks so much for the help!! Will be compiling all my bots from now on, never realized the performance difference was that different