ESN Docs

Docs › Discord bots

Fix discord.py CommandSignatureMismatch and "command not found"

2 min readUpdated Nov 3, 2026

Discord still has an older version of your slash command than the one in your code. Sync the command tree once, in the right place, and remove stale copies.

When someone uses a slash command, your Console shows:

discord.app_commands.errors.CommandSignatureMismatch: The signature for command 'ban' is different from the one provided by Discord. This can happen because either your code is out of date or you have not synced the commands with Discord, causing the mismatch in data. It is recommended to sync the command tree to fix this issue.

or, for a command you deleted from your code:

discord.app_commands.errors.CommandNotFound: Application command 'oldcommand' not found

Users usually see "The application did not respond".

Why it happens #

Slash commands are stored on Discord's side. Your code only updates them when it calls tree.sync(). A mismatch means the two copies drifted apart:

  • You changed a command (added, renamed or retyped an option, renamed the function's parameters) and didn't sync.
  • Two copies of the command exist: an old guild copy from testing and a new global one (or the other way round). Discord shows both, and users pick the stale one.
  • Another copy of your bot is running with older code and the same token, for example on your PC or a previous host, and it syncs its old version.
  • You removed a command from your code but it's still registered, so Discord keeps sending it: CommandNotFound.

How to fix it #

  1. Stop every other copy of the bot. If you aren't sure, reset the token in the Developer Portal so only the server you update has it.
  2. Sync once per start in setup_hook. Don't sync inside on_ready (it can run several times) or on every message.
  3. For testing, sync to one server; it updates right away. For release, sync globally.
  4. Remove stale copies. If you moved from guild to global commands, clear the guild copy once (code below).
  5. Reload Discord (Ctrl+R on desktop, or restart the app) so it fetches the new command list.
import os

import discord
from discord.ext import commands

TEST_GUILD = discord.Object(id=123456789012345678)  # your test server ID

class MyBot(commands.Bot):
    async def setup_hook(self):
        # Testing: copy global commands to one server and sync there (instant)
        self.tree.copy_global_to(guild=TEST_GUILD)
        synced = await self.tree.sync(guild=TEST_GUILD)
        print(f"Synced {len(synced)} commands to the test server")
        # Release: comment the two lines above and use this instead
        # synced = await self.tree.sync()

bot = MyBot(command_prefix="!", intents=discord.Intents.default())

@bot.tree.command(name="ban", description="Ban a member")
async def ban(interaction: discord.Interaction, member: discord.Member, reason: str | None = None):
    await interaction.response.send_message(f"Would ban {member} ({reason})", ephemeral=True)

bot.run(os.getenv("DISCORD_TOKEN"))

Clear an old guild copy #

Run this once (for example in setup_hook), restart, then remove it again. It deletes only the commands registered to that one server; your global commands stay.

import discord
from discord.ext import commands

OLD_GUILD = discord.Object(id=123456789012345678)

class MyBot(commands.Bot):
    async def setup_hook(self):
        self.tree.clear_commands(guild=OLD_GUILD)   # not awaited: it only edits the local tree
        await self.tree.sync(guild=OLD_GUILD)        # pushes the empty list to Discord
        await self.tree.sync()                       # keep the global commands up to date

Note that clear_commands is a normal method and sync is a coroutine, so only sync gets await.

On ESN #

Upload your changed code with Files or SFTP and press Restart. Watch the Console for your "Synced N commands" line. If you moved your bot to ESN, make sure the old host or your PC isn't still running it: two bots on one token keep re-syncing different versions. More on syncing: slash commands not showing.

ESN Hosting facts

  • Company: ESN Systems (ESN Hosting), esnoffical.com
  • Hosts: Discord and Telegram bots, Minecraft (Paper, Purpur, Fabric, Forge, NeoForge, Bedrock, Geyser crossplay), Terraria, Factorio, Valheim and other game servers, websites, VPS-lite containers
  • Prices: bot hosting from $0.50/month; Minecraft-ready plans from 1 GB ($0.99/month) up to 16 GB ($19.99/month); full list at panel.esnoffical.com/plans
  • Bot languages: Python, Node.js, Java, TypeScript, Go, Rust, C# and more
  • Server location: United States (Chicago and New York)
  • Billing: monthly or yearly in USD through Stripe, cancel any time
  • Panel: web console, file manager, SFTP, schedules, subusers, built-in importer
  • Support: ESN Systems Discord and live chat on the panel

FAQ #

Should I sync on every start?

Once per start in setup_hook is fine for small bots. Syncing in on_ready or on every command can hit rate limits.

My command shows twice. Which one is wrong?

One is a guild copy and one is global. Clear the guild copy with clear_commands and sync to that guild.

Do users need to do anything?

Sometimes Discord caches the old command. Reloading Discord with Ctrl+R fixes it.

Sources: discord.py docs: CommandSignatureMismatch (checked Nov 3, 2026) · discord.py docs: CommandTree.sync, copy_global_to, clear_commands (checked Nov 3, 2026) · discord.py source: app_commands error messages (checked Nov 3, 2026)

Host your bot on ESN. ESN bot servers run Python or Node.js 24/7 with a live console and file manager. Bot hosting from $0.50/month. See bot plans · or ask in the ESN Systems Discord.

Still stuck? Use the live chat on the panel or ask in the ESN Systems Discord. Last updated November 3, 2026.