Merge pull request #46078 from xxxigm/fix/discord-slash-command-100-cap

fix(discord): cap slash commands at Discord's 100-command limit
This commit is contained in:
kshitij
2026-06-16 02:05:31 +05:30
committed by GitHub
2 changed files with 83 additions and 0 deletions
+31
View File
@@ -31,6 +31,12 @@ _DISCORD_COMMAND_SYNC_STATE_SUBDIR = "gateway"
_DISCORD_COMMAND_SYNC_STATE_FILENAME = "discord_command_sync_state.json"
_DISCORD_COMMAND_SYNC_MUTATION_INTERVAL_SECONDS = 4.5
_DISCORD_COMMAND_SYNC_MAX_RATE_LIMIT_SLEEP_SECONDS = 30.0
# Discord enforces a hard cap of 100 global application (slash) commands per
# app. Registering more makes the ENTIRE sync fail with error 30032
# ("Maximum number of application commands reached"), which silently breaks
# every slash command — not just the overflow ones. We keep the desired set
# at or below this limit at registration time.
_DISCORD_MAX_APP_COMMANDS = 100
try:
import discord
@@ -3518,6 +3524,11 @@ class DiscordAdapter(BasePlatformAdapter):
)
already_registered: set[str] = set()
# Native commands above are registered first and are the highest
# priority, so they always survive the 100-command cap. Reserve one
# slot for the consolidated ``/skill`` group registered further below.
slot_cap = _DISCORD_MAX_APP_COMMANDS - 1
dropped_over_cap = 0
try:
from hermes_cli.commands import COMMAND_REGISTRY, _is_gateway_available, _resolve_config_gates
@@ -3535,6 +3546,9 @@ class DiscordAdapter(BasePlatformAdapter):
discord_name = cmd_def.name.lower()[:32]
if discord_name in already_registered:
continue
if len(already_registered) >= slot_cap:
dropped_over_cap += 1
continue
auto_cmd = _build_auto_slash_command(
cmd_def.name,
cmd_def.description,
@@ -3567,6 +3581,9 @@ class DiscordAdapter(BasePlatformAdapter):
discord_name = plugin_name.lower()[:32]
if discord_name in already_registered:
continue
if len(already_registered) >= slot_cap:
dropped_over_cap += 1
continue
auto_cmd = _build_auto_slash_command(
plugin_name,
plugin_desc,
@@ -3589,6 +3606,20 @@ class DiscordAdapter(BasePlatformAdapter):
# supporting up to 25 categories × 25 skills = 625 skills.
self._register_skill_group(tree)
if dropped_over_cap:
# Staying under the cap keeps the whole sync succeeding; without
# this guard a single over-limit command makes Discord reject the
# entire batch (error 30032), breaking every slash command.
logger.warning(
"[%s] Reached Discord's limit of %d slash commands; skipped %d "
"lower-priority command(s) to keep the command sync working. "
"Disable slash commands you don't need or trim installed plugins "
"to surface them all.",
self.name,
_DISCORD_MAX_APP_COMMANDS,
dropped_over_cap,
)
# Optional defense-in-depth: hide every slash command from non-admin
# guild members in Discord's slash picker. Server-side authorization
# (``_check_slash_authorization``) is the actual gate; this is purely