TerrorByte
TerrorByte
DIAdiscord.js - Imagine an app
Created by TerrorByte on 11/25/2023 in #djs-questions
Receiving "ShardingReadyTimeout" even though ready event is firing
Hi there! I'm dealing with a strange problem and I'm not sure how to handle it. I'm receiving a ShardingReadyTimeout error, but the ready event is being fired before the error is occuring, so I therefore not sure how to handle it. I'm pretty sure it's being caused by my event handler, but I'm not sure why or how. Essentially, when the bot is actually created, it's firing a loadEvents method which is loading all the event files within my event directory, and attaching them to the client object. An event has a type of:
export type Event = {
name: keyof RestEvents | string
once: boolean
rest: boolean
execute: (...args: any[]) => void | Promise<void>
}
export type Event = {
name: keyof RestEvents | string
once: boolean
rest: boolean
execute: (...args: any[]) => void | Promise<void>
}
My index.ts, which is the sharding manager:
import { ShardingManager } from "discord.js"
import { getConfig } from "./modules/config"

const config = getConfig()
const manager = new ShardingManager("./bot.js", { totalShards: config.shards, token: `${config.token}` })

manager.on("shardCreate", shard => {
console.log(`Launched shard ${shard.id}`)
})

process.on("unhandledRejection", err => {
console.log((err as Error).stack, "error")
})

void manager.spawn()
import { ShardingManager } from "discord.js"
import { getConfig } from "./modules/config"

const config = getConfig()
const manager = new ShardingManager("./bot.js", { totalShards: config.shards, token: `${config.token}` })

manager.on("shardCreate", shard => {
console.log(`Launched shard ${shard.id}`)
})

process.on("unhandledRejection", err => {
console.log((err as Error).stack, "error")
})

void manager.spawn()
My client.ts, which is the actual bot code:
import { GatewayIntentBits, Partials } from "discord.js"
import { getConfig } from "./modules/config"
import CrystalClient from "./types/CrystalClient"

const config = getConfig()
const client = new CrystalClient({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildVoiceStates,
],
partials: [Partials.User, Partials.Message, Partials.GuildMember, Partials.ThreadMember],
})

void client.login(config.token)
import { GatewayIntentBits, Partials } from "discord.js"
import { getConfig } from "./modules/config"
import CrystalClient from "./types/CrystalClient"

const config = getConfig()
const client = new CrystalClient({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildVoiceStates,
],
partials: [Partials.User, Partials.Message, Partials.GuildMember, Partials.ThreadMember],
})

void client.login(config.token)
I'm extending the discord.js Client object to support some of my own functionality, so here is that file:
import { Client, type ClientOptions, Collection, type GuildBasedChannel } from "discord.js"
import { loadEvents } from "../modules/utils/eventHandler"
import { type Command } from "./Command"

export default class CrystalClient extends Client {
static commands: Collection<string, Command> // Not used yet, can be ignored
static events: Collection<string, (...args: any[]) => void> // Not used yet, can be ignored
static guilds: string[] // Not used yet, can be ignored
static channels: GuildBasedChannel[] = [] // Not used yet, can be ignored
private static client: CrystalClient

constructor(options: ClientOptions) {
super(options)
CrystalClient.client = this

CrystalClient.commands = new Collection() // Not used yet, can be ignored
CrystalClient.events = new Collection() // Not used yet, can be ignored

void loadEvents(CrystalClient.client)
}

static getClient(): CrystalClient {
return CrystalClient.client
}
}
import { Client, type ClientOptions, Collection, type GuildBasedChannel } from "discord.js"
import { loadEvents } from "../modules/utils/eventHandler"
import { type Command } from "./Command"

export default class CrystalClient extends Client {
static commands: Collection<string, Command> // Not used yet, can be ignored
static events: Collection<string, (...args: any[]) => void> // Not used yet, can be ignored
static guilds: string[] // Not used yet, can be ignored
static channels: GuildBasedChannel[] = [] // Not used yet, can be ignored
private static client: CrystalClient

constructor(options: ClientOptions) {
super(options)
CrystalClient.client = this

CrystalClient.commands = new Collection() // Not used yet, can be ignored
CrystalClient.events = new Collection() // Not used yet, can be ignored

void loadEvents(CrystalClient.client)
}

static getClient(): CrystalClient {
return CrystalClient.client
}
}
12 replies