Skip to content

fix(discord): delete stale slash commands before creating new ones - #29134

Closed
kasnol wants to merge 1 commit into
NousResearch:mainfrom
kasnol:fix/discord-slash-command-cap
Closed

fix(discord): delete stale slash commands before creating new ones#29134
kasnol wants to merge 1 commit into
NousResearch:mainfrom
kasnol:fix/discord-slash-command-cap

Conversation

@kasnol

@kasnol kasnol commented May 20, 2026

Copy link
Copy Markdown

What

_safe_sync_slash_commands() reconciles the bot's global slash commands on connect. It created net-new commands first and deleted removed ones last.

Problem

Discord enforces the 100 global-command cap at create time. When the command set changes substantially (e.g. after pulling an update that renames/adds commands), the old commands are still registered on Discord while the new ones are created one-by-one. The transient total can exceed 100, and Discord rejects the create with HTTP 400 code 30032.

Because the deletions of now-removed commands ran after the create loop, that rejection aborts the sync before any space is freed. The reconcile then fails identically on every reconnect — the bot is stuck and never recovers on its own.

Fix

Delete commands that are no longer desired before creating new ones. Peak server-side count is bounded by max(len(existing), len(desired)) ≤ 100 by construction. The old trailing delete loop is removed (redundant). Counting/summary semantics unchanged.

Test

Adds test_safe_sync_deletes_stale_before_creating_new asserting every stale delete is issued before the first net-new create. Fails on the old ordering, passes with the fix. Full test_discord_connect.py suite (17 tests) green.

Reproduction

  1. Run a bot whose desired command set is near the cap and that has a prior (different-named) global command set still registered on Discord — e.g. after pulling an update that renames/adds commands.
  2. Connect with DISCORD_COMMAND_SYNC_POLICY=safe (the default → _safe_sync_slash_commands).
  3. Sync creates net-new commands before deleting removed ones; the server-side global count transiently exceeds 100.

Discord rejects the create:

HTTP 400 Bad Request (error code: 30032):
Maximum number of application commands reached (100)

The exception aborts _safe_sync_slash_commands before the trailing stale-delete loop runs, so space is never freed and every subsequent reconnect reproduces the same failure (the bot's slash commands stay wedged until manual intervention).

The added regression test reproduces the ordering deterministically without a live Discord connection.

Workaround for affected users

Set DISCORD_COMMAND_SYNC_POLICY=bulk — uses Discord's atomic bulk overwrite (tree.sync()), one request, never transiently exceeds the cap.

Runtime verification

Verified on a live bot under the default safe policy after applying this patch:

[Discord] Safely reconciled 48 slash command(s): unchanged=0 updated=0 recreated=47 created=1 deleted=0

No 30032, sync completed in one pass, state recorded successfully. The patched _safe_sync_slash_commands (with delete-stale-first ordering) executed end-to-end against a real Discord application.

Discord enforces the 100 global application-command cap server-side at
create time. _safe_sync_slash_commands created net-new commands first and
deleted stale ones last, so a large command-set delta (e.g. after an
update that renames/adds commands) could transiently push the server
count past 100. Discord then rejects with HTTP 400 code 30032, the
exception aborts the sync, and because the stale deletions ran last they
never execute to free space — leaving the app wedged on every reconnect.

Prune stale commands before creating new ones so the peak server-side
count never exceeds max(len(existing), len(desired)) <= 100. The trailing
delete loop is removed (now redundant). Counting/summary semantics are
unchanged.

Adds a regression test asserting every stale delete precedes the first
net-new create (fails on the old ordering, passes with the fix).
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists platform/discord Discord bot adapter comp/gateway Gateway runner, session dispatch, delivery duplicate This issue or pull request already exists labels May 20, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #24371 (identical fix: reorder Discord slash command sync to delete stale commands before creating new ones). Also see broader #28800 which adds budget-based cap enforcement.

@kasnol

kasnol commented May 27, 2026

Copy link
Copy Markdown
Author

Closing as duplicate — same fix already proposed in #19366 (2026-05-03) and #24371 (2026-05-12). Closing this one to keep review queue tidy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists platform/discord Discord bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants