AI Troubleshooting
This guide covers common issues you might encounter when working with CommandKit's AI system and how to resolve them.
Common Issues
AI Not Responding to Messages
Symptoms: Bot doesn't respond when mentioned or keywords are used.
Possible Causes:
-
AI plugin not registered
commandkit.config.tsimport { ai } from '@commandkit/ai';
export default defineConfig({
plugins: [ai()], // Make sure this is included
}); -
Message filter too restrictive
// Check your message filter
messageFilter: async (commandkit, message) => {
console.log('Filtering message:', message.content);
const shouldProcess = message.mentions.users.has(message.client.user.id);
console.log('Should process:', shouldProcess);
return shouldProcess;
}; -
Missing bot permissions
// Bot needs these intents
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent, // Required for message content
],
});
AI Model Configuration Errors
Symptoms: Errors about missing AI model or configuration.
Solutions:
-
Check API keys
# Make sure environment variables are set
GOOGLE_API_KEY=your_api_key_here
OPENAI_API_KEY=your_api_key_here -
Verify model configuration
configureAI({
selectAiModel: async (ctx, message) => {
// Make sure this function is defined and returns a model
if (!process.env.GOOGLE_API_KEY) {
throw new Error('GOOGLE_API_KEY environment variable not set');
}
return {
model: google.languageModel('gemini-2.0-flash'),
};
},
}); -
Handle model initialization errors
selectAiModel: async (ctx, message) => {
try {
return {
model: google.languageModel('gemini-2.0-flash'),
};
} catch (error) {
console.error('Model initialization failed:', error);
throw new Error('AI model not available');
}
};
Command Parameters Not Working
Symptoms: AI commands receive undefined or incorrect parameters.
Solutions:
-
Check Zod schema definition
export const aiConfig = {
parameters: z.object({
// Make sure parameter names match what the AI should provide
username: z.string().describe('The username to greet'),
message: z.string().optional().describe('Optional greeting message'),
}),
} satisfies AiConfig; -
Validate parameters in command
export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
console.log('Received parameters:', ctx.ai.params);
const { username, message } = ctx.ai.params;
if (!username) {
await ctx.message.reply('❌ Username parameter is required');
return;
}
// Continue with command logic
}; -
Improve parameter descriptions
parameters: z.object({
userId: z
.string()
.describe('Discord user ID (numbers only, like 123456789012345678)'),
duration: z
.number()
.describe('Duration in minutes (e.g., 30 for 30 minutes)'),
reason: z.string().optional().describe('Optional reason for the action'),
});
Rate Limiting Issues
Symptoms: AI stops responding or shows rate limit errors.
Solutions:
-
Implement user-level rate limiting
const userCooldowns = new Map<string, number>();
messageFilter: async (commandkit, message) => {
const userId = message.author.id;
const now = Date.now();
const cooldown = userCooldowns.get(userId) || 0;
if (now < cooldown + 30000) {
// 30 second cooldown
return false;
}
userCooldowns.set(userId, now);
return message.mentions.users.has(message.client.user.id);
}; -
Add timeout configuration
selectAiModel: async (ctx, message) => ({
model: myModel,
abortSignal: AbortSignal.timeout(30000), // 30 second timeout
}); -
Handle rate limit errors gracefully
onError: async (ctx, message, error) => {
if (error.message.includes('rate limit')) {
await message.reply(
"⏰ I'm being rate limited. Please wait a moment and try again.",
);
} else {
await message.reply(
'❌ An error occurred while processing your request.',
);
}
};
Memory and Performance Issues
Symptoms: Bot becomes slow or runs out of memory.
Solutions:
-
Clear context store data
export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
try {
// Use context store
ctx.store.set('data', someData);
// Process command
await processCommand();
} finally {
// Clear large objects from store
ctx.store.clear();
}
}; -
Limit AI steps and tokens
selectAiModel: async (ctx, message) => ({
model: myModel,
maxSteps: 5, // Limit tool calls
maxTokens: 1000, // Limit response length
}); -
Implement caching for expensive operations
async function fetchUserData(userId: string) {
'use cache';
const cacheKey = `user:${userId}`;
cacheTag(cacheKey);
cacheLife('5m');
const userData = await getUserDataFromDatabase(userId);
return userData;
}
export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
const userData = await fetchUserData(ctx.message.author.id);
};
Debugging Techniques
Enable Debug Logging
configureAI({
onProcessingStart: async (ctx, message) => {
console.log('AI processing started:', {
user: message.author.username,
content: message.content.substring(0, 100),
guild: message.guild?.name,
});
},
onResult: async (ctx, message, result) => {
console.log('AI result:', {
text: result.text?.substring(0, 100),
toolCalls: result.toolCalls?.length || 0,
finishReason: result.finishReason,
});
},
onError: async (ctx, message, error) => {
console.error('AI error:', {
error: error.message,
stack: error.stack,
user: message.author.id,
content: message.content,
});
},
});
Test AI Commands Manually
import { useAI } from '@commandkit/ai';
// Test AI processing manually
const aiPlugin = useAI();
await aiPlugin.executeAI(message);
Validate Tool Registration
// Check if tools are registered correctly
onAfterCommandsLoad: async (ctx) => {
const commands = ctx.commandkit.commandHandler.getCommandsArray();
const aiCommands = commands.filter((cmd) => 'ai' in cmd.data);
console.log(
'AI commands registered:',
aiCommands.map((cmd) => cmd.data.command.name),
);
};
Environment-Specific Issues
Development Environment
// Add development-specific debugging
if (process.env.NODE_ENV === 'development') {
configureAI({
onError: async (ctx, message, error) => {
// Show full error details in development
await message.reply(
`Debug Error: ${error.message}\n\`\`\`${error.stack}\`\`\``,
);
},
});
}
Production Environment
// Production error handling
if (process.env.NODE_ENV === 'production') {
configureAI({
onError: async (ctx, message, error) => {
// Log to monitoring service
await logError(error, {
userId: message.author.id,
guildId: message.guildId,
command: 'ai',
});
// Send generic error to user
await message.reply('An error occurred. Please try again later.');
},
});
}
Discord API Issues
Missing Permissions
export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
// Check bot permissions
const botMember = ctx.message.guild?.members.me;
if (!botMember?.permissions.has('SendMessages')) {
console.error('Bot missing SendMessages permission');
return;
}
// Check specific permissions for command
if (!botMember.permissions.has('ManageMessages')) {
await ctx.message.reply(
'❌ I need "Manage Messages" permission to use this command.',
);
return;
}
};
Channel Access Issues
messageFilter: async (commandkit, message) => {
// Check if bot can send messages in the channel
if (!message.channel.isSendable()) {
console.log('Cannot send messages in channel:', message.channelId);
return false;
}
return message.mentions.users.has(message.client.user.id);
};
Common Error Messages
"No AI model selected"
Solution: Make sure you've configured selectAiModel
:
configureAI({
selectAiModel: async (ctx, message) => ({
model: google.languageModel('gemini-2.0-flash'),
}),
});
"AI plugin is not registered"
Solution: Add the AI plugin to your configuration:
import { ai } from '@commandkit/ai';
export default defineConfig({
plugins: [ai()],
});
"Cannot read properties of undefined"
Solution: Check parameter validation:
export const ai: AiCommand<typeof aiConfig> = async (ctx) => {
// Add null checks
if (!ctx.ai.params) {
await ctx.message.reply('❌ No parameters provided');
return;
}
const { username } = ctx.ai.params;
if (!username) {
await ctx.message.reply('❌ Username is required');
return;
}
};
Performance Monitoring
Track Response Times
configureAI({
onProcessingStart: async (ctx, message) => {
ctx.store.set('startTime', Date.now());
},
onProcessingFinish: async (ctx, message) => {
const startTime = ctx.store.get('startTime');
if (startTime) {
const duration = Date.now() - startTime;
console.log(`AI processing took ${duration}ms`);
if (duration > 10000) {
// Warn if over 10 seconds
console.warn('Slow AI response detected');
}
}
},
});
Monitor Token Usage
onResult: async (ctx, message, result) => {
if (result.usage) {
console.log('Token usage:', {
prompt: result.usage.promptTokens,
completion: result.usage.completionTokens,
total: result.usage.totalTokens,
});
}
};
Getting Help
If you're still experiencing issues:
- Check the console logs for detailed error messages
- Verify your environment variables are set correctly
- Test with a simple AI command first
- Check Discord bot permissions in the server
- Review the AI model documentation for your provider
- Join the CommandKit Discord for community support