Updating to v14

Before you start

v14 requires Node 16.9 or higher to use, so make sure you're up to date. To check your Node.js version, use node --version in your terminal or command prompt, and if it's not high enough, update it! There are many resources online to help you with this step based on your host system.

Various packages are now included in v14

If you previously had @discordjs/builders, @discordjs/formatters, @discordjs/rest, or discord-api-types manually installed, it's highly recommended that you uninstall the packages to avoid package version conflicts.

npm
yarn
pnpm

_10
npm uninstall @discordjs/builders @discordjs/formatters @discordjs/rest discord-api-types

Breaking Changes

API version

discord.js v14 makes the switch to Discord API v10!

Common Breakages

Enum Values

Any areas that used to accept a string or number type for an enum parameter will now only accept a number.

In addition, the old enums exported by discord.js v13 and lower are replaced with new enums from discord-api-types.

New enum differences

Most of the difference between enums from discord.js and discord-api-types can be summarized as so:

  1. Enums are singular, i.e., ApplicationCommandOptionTypes -> ApplicationCommandOptionType
  2. Enums that are prefixed with Message no longer have the Message prefix, i.e., MessageButtonStyles -> ButtonStyle
  3. Enum values are PascalCase rather than SCREAMING_SNAKE_CASE, i.e., .CHAT_INPUT -> .ChatInput

You might be inclined to a raw number (most commonly referred to as magic numbers) instead of enum values. This is highly discouraged. Enums provide more readability and are more resistant to changes in the API. Magic numbers can obscure the meaning of your code in many ways. Check out this blog post if you want more context on as to why they shouldn't be used.

Magic Numbers Warning

Common enum breakages

Areas like Client initialization, JSON slash commands and JSON message components will likely need to be modified to accommodate these changes:

Common Client Initialization Changes

_10
- import { Client, Intents } = from 'discord.js';
_10
+ import { Client, GatewayIntentBits, Partials } = from 'discord.js';
_10
_10
- const client = new Client({ intents: [Intents.FLAGS.GUILDS], partials: ['CHANNEL'] });
_10
+ const client = new Client({ intents: [GatewayIntentBits.Guilds], partials: [Partials.Channel] });

Common Application Command Data changes

_13
+ import { ApplicationCommandType, ApplicationCommandOptionType } = from 'discord.js';
_13
_13
const command = {
_13
name: 'ping',
_13
- type: 'CHAT_INPUT',
_13
+ type: ApplicationCommandType.ChatInput,
_13
options: [{
_13
name: 'option',
_13
description: 'A sample option',
_13
- type: 'STRING',
_13
+ type: ApplicationCommandOptionType.String,
_13
}],
_13
};

Common Button Data changes

_10
+ import { ButtonStyle } = from 'discord.js';
_10
_10
const button = {
_10
label: 'test',
_10
- style: 'PRIMARY',
_10
+ style: ButtonStyle.Primary,
_10
customId: '1234'
_10
}

Removal of method-based type guards

Channels

Some channel type guard methods that narrowed to one channel type have been removed. Instead compare the type property against a ChannelType enum member to narrow channels.


_10
- channel.isText();
_10
+ channel.type === ChannelType.GuildText;
_10
_10
- channel.isVoice();
_10
+ channel.type === ChannelType.GuildVoice;
_10
_10
- channel.isDM();
_10
+ channel.type === ChannelType.DM;

Builders

Builders are no longer returned by the API like they were previously. For example, you send the API an EmbedBuilder but you receive an Embed of the same data. This may affect how your code handles received structures such as components. Refer to message component changes section for more details.

Added disableValidators() and enableValidators() as top-level exports which disable or enable validation (enabled by default).

Consolidation of create & edit parameters

Various create() and edit() methods on managers and objects have had their parameters consolidated. The changes are below:

Activity

The following properties have been removed as they are not supported by the API:

  • Activity#id
  • Activity#platform
  • Activity#sessionId
  • Activity#syncId

Application

Application#fetchAssets() has been removed as it is no longer supported by the API.

BitField

  • BitField constituents now have a BitField suffix to avoid naming conflicts with the enum names:

_23
- new Permissions();
_23
+ new PermissionsBitField();
_23
_23
- new MessageFlags();
_23
+ new MessageFlagsBitField();
_23
_23
- new ThreadMemberFlags();
_23
+ new ThreadMemberFlagsBitField();
_23
_23
- new UserFlags();
_23
+ new UserFlagsBitField();
_23
_23
- new SystemChannelFlags();
_23
+ new SystemChannelFlagsBitField();
_23
_23
- new ApplicationFlags();
_23
+ new ApplicationFlagsBitField();
_23
_23
- new Intents();
_23
+ new IntentsBitField();
_23
_23
- new ActivityFlags();
_23
+ new ActivityFlagsBitField();

  • #FLAGS has been renamed to #Flags

CDN

The methods that return CDN URLs have changed. Here is an example on a User:


_10
- const url = user.displayAvatarURL({ dynamic: true, format: "png", size: 1024 });
_10
+ const url = user.displayAvatarURL({ extension: "png", size: 1024 });

Dynamic URLs use ImageURLOptions and static URLs use BaseImageURLOptions. Since dynamic URLs are returned by default, this option has been renamed to forceStatic which forces the return of a static URL. Additionally, format has been renamed to extension.

CategoryChannel

CategoryChannel#children is no longer a Collection of channels the category contains. It is now a CategoryChannelChildManager. This also means CategoryChannel#createChannel() has been moved to the CategoryChannelChildManager.

Channel

The following type guards have been removed:

  • Channel#isText()
  • Channel#isVoice()
  • Channel#isDirectory()
  • Channel#isDM()
  • Channel#isGroupDM()
  • Channel#isCategory()
  • Channel#isNews()

Refer to this section for more context.

The base channel class is now BaseChannel.

Client

The restWsBridgeTimeout client option has been removed.

CommandInteractionOptionResolver

CommandInteractionOptionResolver#getMember() no longer has a parameter for required.1

Constants

  • Many constant objects and key arrays are now top-level exports. For example:

_10
- import { Constants } = from 'discord.js';
_10
- const { Colors } = Constants;
_10
+ import { Colors } = from 'discord.js';

  • The refactored constants structures have PascalCase member names as opposed to SCREAMING_SNAKE_CASE member names.

  • Many of the exported constants structures have been replaced and renamed:


_11
- Opcodes
_11
+ GatewayOpcodes
_11
_11
- WSEvents
_11
+ GatewayDispatchEvents
_11
_11
- WSCodes
_11
+ GatewayCloseCodes
_11
_11
- InviteScopes
_11
+ OAuth2Scopes

Events

The message and interaction events are now removed. Use Client#messageCreate and Client#interactionCreate instead.

Client#applicationCommandCreate, Client#applicationCommandDelete, and Client#applicationCommandUpdate have all been removed.2

The Client#threadMembersUpdate event now emits the users that were added, the users that were removed, and the thread respectively.

GuildBanManager

Developers should utilise deleteMessageSeconds instead of days and deleteMessageDays:


_10
<GuildBanManager>.create('123456789', {
_10
- days: 3
_10
- deleteMessageDays: 3
_10
+ deleteMessageSeconds: 3 * 24 * 60 * 60
_10
});

deleteMessageDays and days are both deprecated and will be removed in the future.

Guild

Guild#setRolePositions() and Guild#setChannelPositions() have been removed. Use RoleManager#setPositions() and GuildChannelManager#setPositions() instead respectively.

Guild#maximumPresences no longer has a default value of 25,000.

Guild#me has been moved to GuildMemberManager#me.3

GuildAuditLogs & GuildAuditLogsEntry

GuildAuditLogs.build() has been removed as it has been deemed defunct. There is no alternative.

The following properties & methods have been moved to the GuildAuditLogsEntry class:

  • GuildAuditLogs.Targets
  • GuildAuditLogs.actionType()
  • GuildAuditLogs.targetType()

GuildMember

GuildMember#pending is now nullable to account for partial guild members.4

IntegrationApplication

IntegrationApplication#summary has been removed as it is no longer supported by the API.

Interaction

Whenever an interaction is replied to and one fetches the reply, it could possibly give an APIMessage if the guild was not cached. However, interaction replies now always return a discord.js Message object with fetchReply as true.

The base interaction class is now BaseInteraction.

Invite

Invite#inviter is now a getter and resolves structures from the cache.

MessageAttachment


_10
- new MessageAttachment(buffer, 'image.png');
_10
+ new AttachmentBuilder(buffer, { name: 'image.png' });

MessageComponent

  • MessageComponents have been renamed as well. They no longer have the Message prefix, and now have a Builder suffix:

_11
- const button = new MessageButton();
_11
+ const button = new ButtonBuilder();
_11
_11
- const selectMenu = new MessageSelectMenu();
_11
+ const selectMenu = new StringSelectMenuBuilder();
_11
_11
- const actionRow = new MessageActionRow();
_11
+ const actionRow = new ActionRowBuilder();
_11
_11
- const textInput = new TextInputComponent();
_11
+ const textInput = new TextInputBuilder();

  • Components received from the API are no longer directly mutable. If you wish to mutate a component from the API, use ComponentBuilder#from(). For example, if you want to make a button mutable:

_10
- const editedButton = receivedButton.setDisabled(true);
_10
_10
+ import { ButtonBuilder } = from 'discord.js';
_10
+ const editedButton = ButtonBuilder.from(receivedButton).setDisabled(true);

MessageManager

The second parameter of MessageManager#fetch() has been removed. The BaseFetchOptions the second parameter once was is now merged into the first parameter.


_10
- messageManager.fetch('1234567890', { cache: false, force: true });
_10
+ messageManager.fetch({ message: '1234567890', cache: false, force: true });

MessageSelectMenu

MessageEmbed


_10
- new MessageEmbed().addField('Inline field title', 'Some value here', true);
_10
_10
+ new EmbedBuilder().addFields([
_10
+ { name: 'one', value: 'one', inline: true },
_10
+ { name: 'two', value: 'two', inline: true },
_10
+]);


_10
- const modal = new Modal();
_10
+ const modal = new ModalBuilder();

PartialTypes

The PartialTypes string array has been removed. Use the Partials enum instead.

In addition to this, there is now a new partial: Partials.ThreadMember.

Permissions

The thread permissions USE_PUBLIC_THREADS and USE_PRIVATE_THREADS have been removed as they are deprecated in the API. Use CREATE_PUBLIC_THREADS and CREATE_PRIVATE_THREADS respectively.

PermissionOverwritesManager

Overwrites are now keyed by the PascalCase permission key rather than the SCREAMING_SNAKE_CASE permission key.

REST Events

apiRequest

This REST event has been removed as discord.js now uses Undici as the underlying request handler. You must now use a Diagnostics Channel. Here is a simple example:

JavaScript
TypeScript

_10
import diagnosticsChannel from 'node:diagnostics_channel';
_10
_10
diagnosticsChannel.channel('undici:request:create').subscribe(({ request }) => {
_10
const { request } = data;
_10
console.log(request.method); // Log the method
_10
console.log(request.path); // Log the path
_10
console.log(request.headers); // Log the headers
_10
console.log(request); // Or just log everything!
_10
});

You can find further examples at the Undici Diagnostics Channel documentation.

apiResponse

This REST event has been renamed to response and moved to Client#rest:


_10
- client.on('apiResponse', ...);
_10
+ client.rest.on('response', ...);

invalidRequestWarning

This REST event has been moved to Client#rest:


_10
- client.on('invalidRequestWarning', ...);
_10
+ client.rest.on('invalidRequestWarning', ...);

rateLimit

This REST event has been renamed to rateLimited and moved to Client#rest:


_10
- client.on('rateLimit', ...);
_10
+ client.rest.on('rateLimited', ...);

RoleManager

Role.comparePositions() has been removed. Use RoleManager#comparePositions() instead.

Sticker

Sticker#tags is now a nullable string (string | null). Previously, it was a nullable array of strings (string[] | null).5

ThreadChannel

The MAX helper used in ThreadAutoArchiveDuration has been removed. Discord has since allowed any guild to use any auto archive time which makes this helper redundant.

ThreadMemberManager

The second parameter of ThreadMemberManager#fetch() has been removed. The BaseFetchOptions the second parameter once was is now merged into the first parameter. In addition, the boolean helper to specify cache has been removed.

Usage is now as follows:


_10
// The second parameter is merged into the first parameter.
_10
- threadMemberManager.fetch('1234567890', { cache: false, force: true });
_10
+ threadMemberManager.fetch({ member: '1234567890', cache: false, force: true });
_10
_10
// The lone boolean has been removed. One must be explicit here.
_10
- threadMemberManager.fetch(false);
_10
+ threadMemberManager.fetch({ cache: false });

Util

Util.removeMentions() has been removed. To control mentions, you should use allowedMentions on BaseMessageOptions instead.

Util.splitMessage() has been removed. This utility method is something the developer themselves should do.

Util.resolveAutoArchiveMaxLimit() has been removed. Discord has since allowed any guild to use any auto archive time which makes this method redundant.

Other functions in Util have been moved to top-level exports so you can directly import them from discord.js.


_10
- import { Util } from 'discord.js';
_10
- Util.escapeMarkdown(message);
_10
_10
+ import { escapeMarkdown } from 'discord.js';
_10
+ escapeMarkdown(message);

.deleted fields have been removed

You can no longer use the deleted property to check if a structure was deleted.6

VoiceChannel

VoiceChannel#editable has been removed. You should use GuildChannel#manageable instead.

VoiceRegion

VoiceRegion#vip has been removed as it is no longer part of the API.

Webhook

The second parameter of Webhook#fetchMessage() no longer allows a boolean to be passed. The cache option in WebhookFetchMessageOptions should be used instead.

Features

ApplicationCommand

NFSW commands are supported.

AutocompleteInteraction

AutocompleteInteraction#commandGuildId has been added which is the id of the guild the invoked application command is registered to.

BaseChannel

Added support for BaseChannel#flags.

Store channels have been removed as they are no longer part of the API.

BaseChannel#url has been added which is a link to a channel, just like in the client.

Additionally, new typeguards have been added:

BaseInteraction

Added BaseInteraction#isRepliable() to check whether a given interaction can be replied to.

ClientApplication

Added support for role connection metadata.

Collection

Collector

A new Collector#ignore event has been added which is emitted whenever an element is not collected by the collector.

Component collector options now use the ComponentType enum values:


_10
+ import { ComponentType } from 'discord.js';
_10
_10
const collector = interaction.channel.createMessageComponentCollector({
_10
filter,
_10
- componentType: 'BUTTON',
_10
+ componentType: ComponentType.Button,
_10
time: 20000
_10
});

CommandInteraction

CommandInteraction#commandGuildId has been added which is the id of the guild the invoked application command is registered to.

CommandInteractionOptionResolver

CommandInteractionOptionResolver#getChannel() now has a third parameter which narrows the channel type.

Events

Added support for Client#guildAuditLogEntryCreate event.

ForumChannel

Added support for forum channels.

Added support for ForumChannel#defaultForumLayout.

Guild

Added support for Guild#setMFALevel() which sets the guild's MFA level.

Added support for Guild#maxVideoChannelUsers. which indicates the maximum number of video channel users.

Added support for Guild#maxStageVideoChannelUsers. which indicates the maximum number of video channel users for stage channels.

Added support for Guild#disableInvites(). which disables the guild's invites.

Added support for the after parameter in Guild#fetchAuditLogs().

GuildChannelManager

videoQualityMode may be used whilst creating a channel to initially set the camera video quality mode.

GuildEmojiManager

Added GuildEmojiManager#delete() and GuildEmojiManager#edit() for managing existing guild emojis.

GuildForumThreadManager

Added GuildForumThreadManager as manager for threads in forum channels.

GuildMember

Added support for GuildMember#flags.

GuildMembersChunk

This object now supports the notFound property.

GuildMemberManager

Added GuildMemberManager#fetchMe() to fetch the client user in the guild.

Added GuildMemberManager#addRole() and GuildMemberManager#removeRole(). These methods allow a single addition or removal of a role respectively to a guild member, even if uncached.

GuildTextThreadManager

Added GuildTextThreadManager as manager for threads in text channels and announcement channels.

Message

Message#position has been added as an approximate position in a thread.

Added support for role subscription data.

MessageReaction

Added MessageReaction#react() to make the client user react with the reaction the class belongs to.

Role

Added support for role subscriptions.

StageChannel

Stage channels now allow messages to be sent in them, much like voice channels.

Sticker

Added support for GIF stickers.

ThreadMemberManager

The new withMember options returns the associated guild member with the thread member.

When fetching multiple thread members alongside withMember, paginated results will be returned. The after and limit option are supported in this scenario.

Webhook

Added Webhook#applicationId.

Added the threadName property in WebhookMessageCreateOptions which allows a webhook to create a post in a forum channel.

Footnotes

  1. https://github.com/discordjs/discord.js/pull/7188 ↩

  2. https://github.com/discordjs/discord.js/pull/6492 ↩

  3. https://github.com/discordjs/discord.js/pull/7669 ↩

  4. https://github.com/discordjs/discord.js/issues/6546 ↩

  5. https://github.com/discordjs/discord.js/pull/8010 ↩

  6. https://github.com/discordjs/discord.js/issues/7091 ↩