# Pycord - AutoShardedBot
import discord
from discord.ext import commands
# Automatically handles sharding
bot = commands.AutoShardedBot(
command_prefix="!",
intents=discord.Intents.default(),
shard_count=None # Auto-determine
)
@bot.event
async def on_ready():
print(f"Logged in on {len(bot.shards)} shards")
for shard_id, shard in bot.shards.items():
print(f"Shard {shard_id}: {shard.latency * 1000:.2f}ms")
@bot.event
async def on_shard_ready(shard_id):
print(f"Shard {shard_id} is ready")
# Get guilds per shard
for shard_id, guilds in bot.guilds_by_shard().items():
print(f"Shard {shard_id}: {len(guilds)} guilds")
Scaling_guide
1-2500 guilds: No sharding required
2500+ guilds: Sharding required by Discord
Recommended: ~1000 guilds per shard
Memory: Each shard runs in separate process
Sharp Edges
Interaction Timeout (3 Second Rule)
Severity: CRITICAL
Situation: Handling slash commands, buttons, select menus, or modals
Symptoms:
User sees "This interaction failed" or "The application did not respond."
Command works locally but fails in production.
Slow operations never complete.
Why this breaks:
Discord requires ALL interactions to be acknowledged within 3 seconds:
Slash commands
Button clicks
Select menu selections
Context menu commands
If you do ANY slow operation (database, API, file I/O) before responding,
you'll miss the window. Discord shows an error even if your bot processes
the request correctly afterward.
After acknowledgment, you have 15 minutes for follow-up responses.
Recommended fix:
Acknowledge immediately, process later
// Discord.js - Defer for slow operations
module.exports = {
async execute(interaction) {
// DEFER IMMEDIATELY - before any slow operation
await interaction.deferReply();
// For ephemeral: await interaction.deferReply({ ephemeral: true });
// Now you have 15 minutes
const result = await slowDatabaseQuery();
const aiResponse = await callLLM(result);
// Edit the deferred reply
await interaction.editReply(`Result: ${aiResponse}`);
}
};
// If you're updating the message
await interaction.deferUpdate();
// If you're sending a new response
await interaction.deferReply({ ephemeral: true });
Missing Privileged Intent Configuration
Severity: CRITICAL
Situation: Bot needs member data, presences, or message content
Symptoms:
Members intent: member lists empty, on_member_join doesn't fire
Presences intent: statuses always unknown/offline
Message content intent: message.content is empty string
Why this breaks:
Discord has 3 privileged intents that require manual enablement:
GUILD_MEMBERS - Member join/leave, member lists
GUILD_PRESENCES - Online status, activities
MESSAGE_CONTENT - Read message text (deprecated for commands)
At 100+ servers, you need Discord verification to keep using them.
Recommended fix:
Step 1: Enable in Developer Portal
1. Go to https://discord.com/developers/applications
2. Select your application
3. Go to Bot section
4. Scroll to Privileged Gateway Intents
5. Toggle ON the intents you need
Use slash commands, buttons, and modals instead of message parsing.
These don't require the Message Content intent.
Command Registration Rate Limited
Severity: HIGH
Situation: Registering slash commands
Symptoms:
Commands not appearing. 429 errors when deploying.
"You are being rate limited" messages.
Commands appear for some guilds but not others.
Why this breaks:
Command registration is rate limited:
Global commands: 200 creates/day, updates take up to 1 hour to propagate
Guild commands: 200 creates/day per guild, instant update
Common mistakes:
Registering commands on every bot startup
Registering in every guild separately
Making changes in a loop without delays
Recommended fix:
Use a separate deploy script (not on startup)
// deploy-commands.js - Run manually, not on bot start
const { REST, Routes } = require('discord.js');
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
async function deploy() {
// For development: Guild commands (instant)
if (process.env.GUILD_ID) {
await rest.put(
Routes.applicationGuildCommands(
process.env.CLIENT_ID,
process.env.GUILD_ID
),
{ body: commands }
);
console.log('Guild commands deployed instantly');
}
// For production: Global commands (up to 1 hour)
else {
await rest.put(
Routes.applicationCommands(process.env.CLIENT_ID),
{ body: commands }
);
console.log('Global commands deployed (may take up to 1 hour)');
}
}
deploy();
# Pycord - Don't sync on every startup
@bot.event
async def on_ready():
# DON'T DO THIS:
# await bot.sync_commands()
print(f"Ready! Commands should already be registered.")
# Instead, sync manually or use a flag
if __name__ == "__main__":
if "--sync" in sys.argv:
# Only sync when explicitly requested
bot.sync_commands_on_start = True
bot.run(token)
Testing workflow
Use guild commands during development (instant updates)
Only deploy global commands when ready for production
Run deploy script manually, not on every restart
Bot Token Exposed
Severity: CRITICAL
Situation: Storing or sharing bot token
Symptoms:
Unauthorized actions from your bot.
Bot joins random servers.
Bot sends spam or malicious content.
"Invalid token" after Discord invalidates it.
Why this breaks:
Your bot token provides FULL control over your bot. Attackers can:
Send messages as your bot
Join servers, create invites
Access all data your bot can access
Potentially take over servers where bot has admin
Discord actively scans GitHub for exposed tokens and invalidates them.
Common exposure points:
Committed to Git
Shared in Discord itself
In client-side code
In public screenshots
Recommended fix:
Never hardcode tokens
// BAD - never do this
const token = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.ABCDEF.xyz...';
// GOOD - environment variables
require('dotenv').config();
client.login(process.env.DISCORD_TOKEN);
Use .gitignore
# .gitignore
.env
.env.local
config.json
If token is exposed
Go to Developer Portal immediately
Regenerate the token
Update all deployments
Review bot activity for unauthorized actions
Check git history and force push to remove if needed
// Load with dotenv
require('dotenv').config();
const token = process.env.DISCORD_TOKEN;
Bot Missing applications.commands Scope
Severity: HIGH
Situation: Slash commands not appearing for users
Symptoms:
Bot is in server but slash commands don't show up.
Typing / shows no commands from your bot.
Commands worked in development server but not others.
Why this breaks:
Discord has two important OAuth scopes:
bot - Traditional bot permissions (messages, reactions, etc.)
applications.commands - Slash command permissions
Many bots were invited with only the bot scope before slash commands
existed. They need to be re-invited with both scopes.
// Required at 2500+ guilds
const manager = new ShardingManager('./bot.js', {
token: process.env.DISCORD_TOKEN,
totalShards: 'auto'
});
manager.spawn();
Modal Must Be First Response
Severity: MEDIUM
Situation: Showing a modal from a slash command or button
Symptoms:
"Interaction has already been acknowledged" error.
Modal doesn't appear.
Works sometimes but not others.
Why this breaks:
Modals have a special requirement: showing a modal MUST be the first
response to an interaction. You cannot:
defer() then showModal()
reply() then showModal()
Think for more than 3 seconds then showModal()
Recommended fix:
Show modal immediately
// CORRECT - modal is first response
async execute(interaction) {
const modal = new ModalBuilder()
.setCustomId('my-modal')
.setTitle('Input Form');
// Show immediately - no defer, no reply first
await interaction.showModal(modal);
}
// WRONG - deferred first
async execute(interaction) {
await interaction.deferReply(); // CAN'T DO THIS
await interaction.showModal(modal); // Will fail
}
If you need to check something first
async execute(interaction) {
// Quick sync check is OK (under 3 seconds)
if (!hasPermission(interaction.user.id)) {
return interaction.reply({
content: 'No permission',
ephemeral: true
});
}
// Show modal (still first interaction response for this path)
await interaction.showModal(modal);
}
Validation Checks
Hardcoded Discord Token
Severity: ERROR
Discord tokens must never be hardcoded
Message: Hardcoded Discord token detected. Use environment variables.
Token Variable Assignment
Severity: ERROR
Tokens should come from environment, not strings
Message: Token assigned from string literal. Use environment variable.
Token in Client-Side Code
Severity: ERROR
Never expose Discord tokens to browsers
Message: Discord credentials exposed client-side. Only use server-side.
Slow Operation Without Defer
Severity: WARNING
Slow operations should be deferred to avoid timeout
Message: Slow operation without defer. Interaction may timeout.
Interaction Without Error Handling
Severity: WARNING
Interactions should have try/catch for graceful errors
Message: Interaction without error handling. Add try/catch.
Using Message Content Intent
Severity: WARNING
Message Content is privileged, prefer slash commands
Message: Using Message Content intent. Consider slash commands instead.
Requesting All Intents
Severity: WARNING
Only request intents you actually need
Message: Requesting all intents. Only enable what you need.
Syncing Commands on Ready Event
Severity: WARNING
Don't sync commands on every bot startup
Message: Syncing commands on startup. Use separate deploy script.
Registering Commands in Loop
Severity: WARNING
Use bulk registration, not individual calls
Message: Registering commands in loop. Use bulk registration.
No Rate Limit Handling
Severity: INFO
Consider handling rate limits for bulk operations
Message: Bulk operation without rate limit handling.
Collaboration
Delegation Triggers
user needs AI-powered Discord bot -> llm-architect (Integrate LLM for conversational Discord bot)
user needs Slack integration too -> slack-bot-builder (Cross-platform bot architecture)
user needs voice features -> voice-agents (Discord voice channel integration)
user needs database for bot data -> postgres-wizard (Store user data, server configs, moderation logs)
user needs workflow automation -> workflow-automation (Discord events trigger workflows)
user needs high availability -> devops (Sharding, scaling, monitoring for large bots)