Skip to main content
Yato currently uses Discord.js v12.5.3, which was released in 2021 and is no longer maintained. This guide covers the migration path to Discord.js v14, the current stable version.
Discord.js v12 does not support many modern Discord features like buttons, select menus, modals, threads, and slash commands natively. Upgrading is essential for continued functionality.

Why upgrade?

Security

v12 receives no security updates or bug fixes.

New features

Native slash commands, buttons, modals, and threads.

Performance

Better memory usage and faster event handling.

Support

Active community support and documentation.

Breaking changes overview

The migration from v12 to v14 involves several major breaking changes:
  1. Intents are required - Must specify which events to receive
  2. Managers replaced Collections - Many .cache properties are now managers
  3. MessageEmbed renamed - Now called EmbedBuilder
  4. Permissions system changed - New PermissionFlagsBits and PermissionsBitField
  5. Message content is privileged - Requires intent for non-slash commands
  6. Many methods return promises - More async/await required

Step-by-step migration

1

Update dependencies

Update package.json to use Discord.js v14:
package.json
{
  "dependencies": {
    "discord.js": "^14.14.1",
    "@discordjs/rest": "^2.2.0",
    "@discordjs/builders": "^1.7.0"
  }
}
Install updates:
npm install
2

Add intents to client

Update client initialization in src/index.js:7:
src/index.js
const Discord = require('discord.js');
const { GatewayIntentBits } = Discord;

// Old (v12)
const client = new Discord.Client({ 
  allowedMentions: { parse: ['users', 'roles'] } 
});

// New (v14)
const client = new Discord.Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.GuildMembers,
    GatewayIntentBits.MessageContent, // Required for prefix commands
    GatewayIntentBits.GuildPresences
  ],
  allowedMentions: { parse: ['users', 'roles'] }
});
MessageContent is a privileged intent. Enable it in the Discord Developer Portal under Bot settings.
3

Update MessageEmbed to EmbedBuilder

Replace all MessageEmbed imports and usage:
// Old (v12)
const { MessageEmbed } = require('discord.js');
const embed = new MessageEmbed()
  .setTitle('Title')
  .setColor(colors.default);

// New (v14)
const { EmbedBuilder } = require('discord.js');
const embed = new EmbedBuilder()
  .setTitle('Title')
  .setColor(colors.default);
This affects many files:
  • src/commands/utilities/ping.js:1
  • src/commands/moderation/ban.js:1
  • src/commands/information/help.js:1
  • And many more command files
4

Update presence/status

Update status setting in src/index.js:41:
// Old (v12)
client.user.setPresence({ 
  activity: { name: status, type: 'LISTENING' }, 
  status: 'idle' 
});

// New (v14)
const { ActivityType } = require('discord.js');
client.user.setPresence({
  activities: [{ name: status, type: ActivityType.Listening }],
  status: 'idle'
});
5

Update permissions

Replace permission strings with PermissionFlagsBits:
// Old (v12) - in src/commands/moderation/ban.js:10
module.exports = {
  userRequiredPermissions: 'BAN_MEMBERS',
  clientRequiredPermissions: 'BAN_MEMBERS'
};

// New (v14)
const { PermissionFlagsBits } = require('discord.js');
module.exports = {
  userRequiredPermissions: PermissionFlagsBits.BanMembers,
  clientRequiredPermissions: PermissionFlagsBits.BanMembers
};
Common permission mappings:
  • BAN_MEMBERSPermissionFlagsBits.BanMembers
  • KICK_MEMBERSPermissionFlagsBits.KickMembers
  • MANAGE_GUILDPermissionFlagsBits.ManageGuild
  • MANAGE_MESSAGESPermissionFlagsBits.ManageMessages
  • CREATE_INSTANT_INVITEPermissionFlagsBits.CreateInstantInvite
6

Update button and component styles

Update button styles in commands like src/commands/information/help.js:23:
const { MessageButton, MessageActionRow } = require('gcommands');

// Old (v12)
const button = new MessageButton()
  .setStyle('url')
  .setLabel('Website')
  .setURL('https://yatobot.netlify.app');

// New (v14) - if using native Discord.js buttons
const { ButtonBuilder, ButtonStyle, ActionRowBuilder } = require('discord.js');
const button = new ButtonBuilder()
  .setStyle(ButtonStyle.Link)
  .setLabel('Website')
  .setURL('https://yatobot.netlify.app');

const row = new ActionRowBuilder()
  .addComponents(button);
If continuing to use gcommands, check their documentation for v14 compatibility.

Command-specific changes

Ban command updates

In src/commands/moderation/ban.js:28:
// Old (v12)
if (!banMember.kickable) {
  // Error handling
}

await banMember.ban({ days: 0, reason: reason });

// New (v14)
if (!banMember.bannable) { // Changed from kickable
  // Error handling
}

await banMember.ban({ 
  deleteMessageSeconds: 0, // Changed from days
  reason: reason 
});

Channel type checks

In src/commands/misc/activities.js:71:
// Old (v12)
if (channel.type !== 'voice') {
  // Error
}

// New (v14)
const { ChannelType } = require('discord.js');
if (channel.type !== ChannelType.GuildVoice) {
  // Error
}

Avatar URLs

Update avatar URL methods throughout:
// Old (v12)
member.user.displayAvatarURL({ dynamic: true, size: 1024 })

// New (v14)
member.user.displayAvatarURL({ extension: 'png', size: 1024 })
// Or for animated avatars:
member.user.displayAvatarURL({ dynamic: true, size: 1024 }) // Still works

gcommands compatibility

gcommands v5.2.4 may not be fully compatible with Discord.js v14. Check for updates or consider alternatives.
Options for handling commands in v14:
Discord.js v14 has built-in slash command support:
const { SlashCommandBuilder } = require('discord.js');

module.exports = {
  data: new SlashCommandBuilder()
    .setName('ping')
    .setDescription('Check bot ping'),
  
  async execute(interaction) {
    await interaction.reply(`Pong! ${interaction.client.ws.ping}ms`);
  }
};

MongoDB updates

Update Mongoose connection in src/index.js:11:
// Old (v12 era)
await mongoose.connect(process.env.MONGO_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

// New (modern Mongoose)
await mongoose.connect(process.env.MONGO_URI);
// These options are now defaults

Testing checklist

After migration, test these features:
  • Bot logs in successfully
  • MongoDB connects
  • Commands load without errors
  • Status updates correctly
  • Slash commands register and work
  • Mention prefix commands work (if keeping them)
  • Arguments are parsed correctly
  • Permissions are checked
  • Embeds display correctly
  • Buttons are clickable
  • Button collectors work
  • Action rows function properly
  • Ban command works
  • Kick command works
  • Permission checks function
  • AniList integration works
  • Reddit fetcher works
  • Image APIs respond
  • Game server queries work

Migration resources

Discord.js Guide

Official migration guide from v13 to v14

Discord.js Docs

Complete v14 API documentation

Gateway Intents

Understanding Discord intents

Slash Commands

Building slash commands in v14
Consider migrating to TypeScript during the v14 upgrade for better type safety and developer experience.

Build docs developers (and LLMs) love