You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js v14发送两个选择菜单报错,求解决方案

问题

我是Discord.js v14的新手,之前使用v13版本。现在遇到一个问题:尝试在同一个ActionRowBuilder中添加两个SelectMenuBuilder,搭配按钮和Embed发送时,触发了组件宽度超限错误。我需要实现发送Embed、两个选择菜单和两个按钮的需求,以下是我的代码及报错信息:

代码

const { SlashCommandBuilder, EmbedBuilder , ButtonBuilder , ActionRowBuilder , SelectMenuBuilder} = require('discord.js');

module.exports = {
  data: new SlashCommandBuilder()
    .setName('bus-test')
    .setDescription('Just testing')
    .addAttachmentOption(option => option.setName('screenshot').setDescription('Upload a screenshot').setRequired(true))
    .addStringOption(option => option.setName('other_drivers').setDescription('Enter all drivers with @').setRequired(true))
    .addStringOption(option => option.setName('passengers').setDescription('Enter all passengers with @').setRequired(true)),
  async execute(interaction) {
    const author = interaction.user;
    const drivers = interaction.options.getString('other_drivers');
    const passengers = interaction.options.getString('passengers');
    const attachment = interaction.options.getAttachment('screenshot');
    const passengersWithDots = passengers.split(' ').map(passengers => `• ${passengers}`).join('\n');
    const driversWithDots = drivers.split(' ').map(driver => `• ${driver}`).join('\n');
    const driversWithMention = `• ${author}\n${driversWithDots}`;

    const embed = new EmbedBuilder()
      .setTitle('**Report System Rules**')
      .setColor('Yellow')
      .setDescription(`${driversWithMention}\n\nPassenger(s)\n${passengersWithDots}`)
      .setImage(attachment.url);

    const selectMenu1 = new SelectMenuBuilder()
      .setCustomId('select_menu1')
      .setPlaceholder('Select an option')
      .addOptions([
        {
          label: 'Option 1',
          value: 'option_1',
        },
        {
          label: 'Option 2',
          value: 'option_2',
        },
      ]);

    const selectMenu2 = new SelectMenuBuilder()
      .setCustomId('select_menu2')
      .setPlaceholder('Select another option')
      .addOptions([
        {
          label: 'Option A',
          value: 'option_a',
        },
        {
          label: 'Option B',
          value: 'option_b',
        },
      ]);

    const button1 = new ButtonBuilder()
      .setCustomId('button1')
      .setLabel('Button 1')
      .setStyle('Primary');

    const button2 = new ButtonBuilder()
      .setCustomId('button2')
      .setLabel('Button 2')
      .setStyle('Danger');

    const row1 = new ActionRowBuilder()
      .addComponents(selectMenu1, selectMenu2);

    const row2 = new ActionRowBuilder()
      .addComponents(button1, button2);

    await interaction.reply({
      embeds: [embed],
      ephemeral: true,
      components: [row1, row2],
    });
  },
};

报错信息

data.components[0].components[1][COMPONENT_LAYOUT_WIDTH_EXCEEDED]: The specified component exceeds the maximum width
    at handleErrors (C:\Users\abodah\Desktop\shawarma\node_modules\@discordjs\rest\dist\index.js:640:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async BurstHandler.runRequest (C:\Users\abodah\Desktop\shawarma\node_modules\@discordjs\rest\dist\index.js:736:23)
    at async REST.request (C:\Users\abodah\Desktop\shawarma\node_modules\@discordjs\rest\dist\index.js:1387:22)
    at async ChatInputCommandInteraction.reply (C:\Users\abodah\Desktop\shawarma\node_modules\discord.js\src\structures\interfaces\InteractionResponses.js:111:5)
    at async Object.execute (C:\Users\x\Desktop\shawarma\commands\bus.js:69:5)
    at async Client.<anonymous> (C:\Users\x\Desktop\shawarma\bot.js:76:5) {
  requestBody: { files: [], json: { type: 4, data: [Object] } },
  rawError: {
    message: 'Invalid Form Body',
    code: 50035,
    errors: { data: [Object] }
  },
  code: 50035,
  status: 400,
  method: 'POST',
解决方法

问题根源是Discord的组件布局规则:每个选择菜单(SelectMenu)会占满整个ActionRow的宽度,所以一个ActionRow里只能放置一个SelectMenu,无法同时容纳两个。

只需要将两个SelectMenu分别放在独立的ActionRowBuilder中,按钮保留在原来的ActionRow里即可。修改后的代码如下:

const { SlashCommandBuilder, EmbedBuilder , ButtonBuilder , ActionRowBuilder , SelectMenuBuilder} = require('discord.js');

module.exports = {
  data: new SlashCommandBuilder()
    .setName('bus-test')
    .setDescription('Just testing')
    .addAttachmentOption(option => option.setName('screenshot').setDescription('Upload a screenshot').setRequired(true))
    .addStringOption(option => option.setName('other_drivers').setDescription('Enter all drivers with @').setRequired(true))
    .addStringOption(option => option.setName('passengers').setDescription('Enter all passengers with @').setRequired(true)),
  async execute(interaction) {
    const author = interaction.user;
    const drivers = interaction.options.getString('other_drivers');
    const passengers = interaction.options.getString('passengers');
    const attachment = interaction.options.getAttachment('screenshot');
    const passengersWithDots = passengers.split(' ').map(passengers => `• ${passengers}`).join('\n');
    const driversWithDots = drivers.split(' ').map(driver => `• ${driver}`).join('\n');
    const driversWithMention = `• ${author}\n${driversWithDots}`;

    const embed = new EmbedBuilder()
      .setTitle('**Report System Rules**')
      .setColor('Yellow')
      .setDescription(`${driversWithMention}\n\nPassenger(s)\n${passengersWithDots}`)
      .setImage(attachment.url);

    const selectMenu1 = new SelectMenuBuilder()
      .setCustomId('select_menu1')
      .setPlaceholder('Select an option')
      .addOptions([
        {
          label: 'Option 1',
          value: 'option_1',
        },
        {
          label: 'Option 2',
          value: 'option_2',
        },
      ]);

    const selectMenu2 = new SelectMenuBuilder()
      .setCustomId('select_menu2')
      .setPlaceholder('Select another option')
      .addOptions([
        {
          label: 'Option A',
          value: 'option_a',
        },
        {
          label: 'Option B',
          value: 'option_b',
        },
      ]);

    const button1 = new ButtonBuilder()
      .setCustomId('button1')
      .setLabel('Button 1')
      .setStyle('Primary');

    const button2 = new ButtonBuilder()
      .setCustomId('button2')
      .setLabel('Button 2')
      .setStyle('Danger');

    // 每个选择菜单单独放在一个ActionRow里
    const row1 = new ActionRowBuilder()
      .addComponents(selectMenu1);
      
    const row2 = new ActionRowBuilder()
      .addComponents(selectMenu2);

    const row3 = new ActionRowBuilder()
      .addComponents(button1, button2);

    await interaction.reply({
      embeds: [embed],
      ephemeral: true,
      components: [row1, row2, row3], // 按顺序传入三个组件行
    });
  },
};

这样修改后,就能正常发送包含Embed、两个选择菜单和两个按钮的消息,不会触发宽度超限的错误。

内容的提问来源于stack exchange,提问作者Abdalrahma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 13:07:44