Guide

Fixing an old discord.js bot for discord.js 14

npm installs discord.js 14, and most tutorials and bots on GitHub were written for 12 or 13. The errors come from a handful of renames, and each has a direct replacement.

6 minute read

Check which version you have with npm ls discord.js. If you would rather move the code forward than pin an old version, these are the changes that break most old bots, with the error each one gives.

Cannot read properties of undefined (reading 'FLAGS')

Intents.FLAGS and Permissions.FLAGS are gone. Intents are GatewayIntentBits:

const { Client, GatewayIntentBits, Partials } = require("discord.js");

const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,   // only if it reads what people type
  ],
  partials: [Partials.Channel],          // with GatewayIntentBits.DirectMessages, to receive DMs
});

MessageContent is privileged: switch it on in the Developer Portal under Bot as well, or Discord refuses the login.

RangeError [BitFieldInvalid]: Invalid bitfield flag or number: GUILDS

The same change: intents: ["GUILDS", "GUILD_MESSAGES"] was version 13. Use the GatewayIntentBits names above.

MessageEmbed is not a constructor

The classes you build messages with were renamed to builders:

  • MessageEmbed: EmbedBuilder
  • MessageActionRow: ActionRowBuilder
  • MessageButton: ButtonBuilder, with ButtonStyle.Primary instead of "PRIMARY"
  • MessageSelectMenu: StringSelectMenuBuilder
  • MessageAttachment: AttachmentBuilder
  • Modal and TextInputComponent: ModalBuilder and TextInputBuilder

EmbedBuilder also takes fields as objects: .addFields({ name: "Level", value: "12" }) in place of .addField("Level", "12"), and a colour as a number or Colors.Blue.

DiscordAPIError[50006]: Cannot send an empty message

channel.send(embed) was version 12. Since 13, everything goes in an object: channel.send({ embeds: [embed] }), channel.send({ content: "hi", files: [attachment] }). A plain string still works: channel.send("hi").

member.hasPermission is not a function

Now member.permissions.has(PermissionFlagsBits.Administrator), with PermissionFlagsBits from discord.js.

Things that fail quietly

  • The message event never fires. It is messageCreate now, and interactionCreate for slash commands and buttons. Nothing warns you; the handler just never runs.
  • Comparisons with old strings are always false. channel.type === "GUILD_TEXT" is now channel.type === ChannelType.GuildText, and activity types are ActivityType.Watching and so on.
  • Prefix commands see empty messages without the Message Content intent, in code and in the Developer Portal. See online but not responding.

Slash commands

Version 14 registers slash commands through the REST client and SlashCommandBuilder; old client.api.applications(...) calls no longer exist. Slash commands in discord.js walks through it.

On SnowServers the console names most of these as they happen, under a Hint: line, and hosting a discord.js bot covers the rest of the setup.