Skip to content

[Bug]: BASE_TYPE_REQUIRED: This field is required' when calling RegisterCommandsGloballyAsync #3203

@TheBoxyBear

Description

@TheBoxyBear

Check The Docs

  • I double checked the docs and couldn't find any useful information.

Verify Issue Source

  • I verified the issue was caused by Discord.Net.

Check your intents

  • I double checked that I have the required intents.

Description

As of today, registering a bot with a single module fails with the server responding error code 50035 BASE_TYPE_REQUIRED: This field is required' which from reading forums, seems to be from either using the wrong post/put or not specifying application/json in the header. The same bot worked a few days ago on the same package version, so it appears to be related to a recent change in Discord's API.

The log does show some errors and warnings, but these same ones were being shown previously.

Although the project is setup to use Docker, the same issue happens regardless or running locally or as a container.

Fond workaround: Wrap the call in an empty try-catch. The commands seem to be still be registering with Discord despite the exception, and it allows the bot to keep running to respond to commands.

Version

3.18.0

Working Version

3.18.0

Logs

Discord.Net v3.18.0 (API v10)
Connecting
You're using the GuildScheduledEvents gateway intent without listening to any events related to that intent, consider removing the intent from your config.
You're using the GuildInvites gateway intent without listening to any events related to that intent, consider removing the intent from your config.
Connected
Error handling Dispatch (GUILD_AVAILABLE)

Sample

Ready to send this snippet Program.cs - Using DI based on the docs

using Microsoft.Extensions.DependencyInjection;

using Discord;
using Discord.WebSocket;
using Discord.Interactions;

using MyNamespace;

const string token = "[redacted]";

IServiceProvider _services = CreateProvider();
DiscordSocketClient _client = _services.GetRequiredService<DiscordSocketClient>();

_client.Log += Log;
_client.Connected += () => Task.CompletedTask;
_client.Ready += async () => await _services.GetRequiredService<InteractionHandler>().Start();

await _client.LoginAsync(TokenType.Bot, token);
await _client.StartAsync();

while (Console.Read() != 'q') ;

static IServiceProvider CreateProvider()
    => new ServiceCollection()
    .AddSingleton<DiscordSocketConfig>()
    .AddSingleton<DiscordSocketClient>()
    .AddSingleton(x => new InteractionService(x.GetRequiredService<DiscordSocketClient>()))
    .AddSingleton<InteractionHandler>()
    .BuildServiceProvider();

static Task Log(LogMessage message)
{
    Console.WriteLine(message.Message);
    return Task.CompletedTask;
}

InteractionHandler.cs - Mostly based on the docs, throws the exception in Start()

using Discord;
using Discord.Interactions;
using Discord.WebSocket;

using System.Reflection;

namespace MyNamespace;

// Primary constructor receiving args from DI
public class InteractionHandler(DiscordSocketClient client, InteractionService handler, IServiceProvider services)
{
    public async Task Start()
    {
        client.InteractionCreated += HandleInteraction;

        await handler.AddModulesAsync(Assembly.GetExecutingAssembly(), services);

        // EXCEPTION HERE - Work around by wrapping in an empty try-catch
        await handler.RegisterCommandsGloballyAsync();
    }

    private async Task HandleInteraction(SocketInteraction interaction)
    {
        // Copied snippet from docs
        try
        {
            // Create an execution context that matches the generic type parameter of your InteractionModuleBase<T> modules.
            var context = new SocketInteractionContext(client, interaction);

            // Execute the incoming command.
            IResult result = await handler.ExecuteCommandAsync(context, services);

            // Due to async nature of InteractionFramework, the result here may always be success.
            // That's why we also need to handle the InteractionExecuted event.
            if (!result.IsSuccess)
                switch (result.Error)
                {
                    case InteractionCommandError.UnmetPrecondition:
                        // implement
                        break;
                    default:
                        break;
                }
        }
        catch
        {
            // If Slash Command execution fails it is most likely that the original interaction acknowledgement will persist. It is a good idea to delete the original
            // response, or at least let the user know that something went wrong during the command execution.
            if (interaction.Type is InteractionType.ApplicationCommand)
                await interaction.GetOriginalResponseAsync().ContinueWith(async (msg) => await msg.Result.DeleteAsync());
        }
    }
}

TestModule - Basic module based on the docs

using Discord.Interactions;

namespace MyNamespace;

public class TestModule : InteractionModuleBase<SocketInteractionContext>
{
    [SlashCommand("echo", "Echo an input")]
    public async Task Echo(string input)
    {
        await RespondAsync(input);
    }
}

Packages

Microsoft.DotNet.ILCompiler
Microsoft.Extensions.Dependencyinjection

  • Included with Docker template
    Microsoft.Extensions.Dependencyinjection
    Microsoft.NET.ILink.Tasks
    Microsoft.VisualStudio.Azure.Containers.Tools.Targets

Environment

  • OS: Windows 11 24H2
  • Architecture: AMD64
  • SDK: .NET 9.0.306

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions