Debugging AI-Generated Code
Common Bugs and How to Fix Them
5 min read
AI coding assistants make predictable mistakes. Knowing these patterns helps you spot and fix issues quickly.
Category 1: Data Handling Bugs
Bug: Unsafe JSON Parsing
// AI Generated
function loadConfig(): Config {
const data = fs.readFileSync('config.json', 'utf-8');
return JSON.parse(data);
}
Problems:
- File might not exist
- File might not be valid JSON
- No runtime type validation
Fix:
import { z } from 'zod';
const ConfigSchema = z.object({
apiKey: z.string(),
port: z.number(),
debug: z.boolean().default(false),
});
function loadConfig(): Config {
try {
const data = fs.readFileSync('config.json', 'utf-8');
return ConfigSchema.parse(JSON.parse(data));
} catch (error) {
if (error instanceof z.ZodError) {
throw new Error(`Invalid config: ${error.message}`);
}
throw new Error('Failed to load config file');
}
}
Bug: Assuming Array Elements Exist
// AI Generated
function getFirstUser(users: User[]): string {
return users[0].name;
}
Problems:
- Array might be empty
- First element might be undefined
Fix:
function getFirstUser(users: User[]): string | null {
return users[0]?.name ?? null;
}
Bug: Mutating Input Parameters
// AI Generated
function sortUsers(users: User[]): User[] {
return users.sort((a, b) => a.name.localeCompare(b.name));
}
Problem: sort() mutates the original array
Fix:
function sortUsers(users: User[]): User[] {
return [...users].sort((a, b) => a.name.localeCompare(b.name));
}
Category 2: Async/Promise Bugs
Bug: Forgetting to Await
// AI Generated
async function processData() {
const data = fetchData(); // Missing await!
return transform(data);
}
Fix:
async function processData() {
const data = await fetchData();
return transform(data);
}
Bug: forEach with Async
// AI Generated
async function sendEmails(users: User[]) {
users.forEach(async (user) => {
await sendEmail(user.email);
});
console.log('All emails sent'); // Lies! Not actually done
}
Fix:
async function sendEmails(users: User[]) {
await Promise.all(users.map(user => sendEmail(user.email)));
console.log('All emails sent');
}
// Or sequentially:
async function sendEmailsSequential(users: User[]) {
for (const user of users) {
await sendEmail(user.email);
}
console.log('All emails sent');
}
Bug: Unhandled Promise Rejection
// AI Generated
function loadData() {
fetch('/api/data')
.then(response => response.json())
.then(data => updateUI(data));
// No .catch()!
}
Fix:
async function loadData() {
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
updateUI(data);
} catch (error) {
showError('Failed to load data');
console.error('Load data error:', error);
}
}
Category 3: State Management Bugs
Bug: Stale Closure
// AI Generated (React)
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCount(count + 1); // Always uses initial count!
}, 1000);
return () => clearInterval(interval);
}, []);
return <div>{count}</div>;
}
Fix:
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCount(prev => prev + 1); // Use updater function
}, 1000);
return () => clearInterval(interval);
}, []);
return <div>{count}</div>;
}
Bug: Missing Dependency in useEffect
// AI Generated
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(setUser);
}, []); // Missing userId!
}
Fix:
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetchUser(userId).then(setUser);
}, [userId]);
}
Category 4: Security Bugs
Bug: Exposed Sensitive Data in Logs
// AI Generated
async function login(email: string, password: string) {
console.log(`Login attempt: ${email}, ${password}`); // Never log passwords!
// ...
}
Fix:
async function login(email: string, password: string) {
console.log(`Login attempt: ${email}`);
// ...
}
Bug: Improper Input Sanitization
// AI Generated
app.get('/search', (req, res) => {
const query = req.query.q;
res.send(`<h1>Results for: ${query}</h1>`); // XSS!
});
Fix:
import { escape } from 'html-escaper';
app.get('/search', (req, res) => {
const query = escape(req.query.q || '');
res.send(`<h1>Results for: ${query}</h1>`);
});
Bug: Path Traversal
// AI Generated
app.get('/files/:filename', (req, res) => {
const filePath = `./uploads/${req.params.filename}`;
res.sendFile(filePath); // Can access ../../../etc/passwd!
});
Fix:
import path from 'path';
app.get('/files/:filename', (req, res) => {
const filename = path.basename(req.params.filename); // Strip path components
const filePath = path.join(__dirname, 'uploads', filename);
// Verify path is within uploads directory
if (!filePath.startsWith(path.join(__dirname, 'uploads'))) {
return res.status(403).send('Access denied');
}
res.sendFile(filePath);
});
Category 5: Performance Bugs
Bug: N+1 Query
// AI Generated
async function getPostsWithAuthors() {
const posts = await db.post.findMany();
return Promise.all(
posts.map(async (post) => ({
...post,
author: await db.user.findUnique({ where: { id: post.authorId } }),
}))
);
}
Fix:
async function getPostsWithAuthors() {
return db.post.findMany({
include: { author: true },
});
}
Bug: Missing Memoization
// AI Generated (React)
function ExpensiveList({ items, filter }) {
const filteredItems = items.filter(item =>
item.name.toLowerCase().includes(filter.toLowerCase())
);
return filteredItems.map(item => <Item key={item.id} {...item} />);
}
Fix:
function ExpensiveList({ items, filter }) {
const filteredItems = useMemo(
() => items.filter(item =>
item.name.toLowerCase().includes(filter.toLowerCase())
),
[items, filter]
);
return filteredItems.map(item => <Item key={item.id} {...item} />);
}
Quick Reference: Bug Fix Patterns
| Bug Type | AI Pattern | Fix |
|---|---|---|
| Missing await | const x = asyncFn() |
const x = await asyncFn() |
| forEach async | arr.forEach(async ...) |
await Promise.all(arr.map(...)) |
| Stale closure | setCount(count + 1) |
setCount(prev => prev + 1) |
| Array mutate | arr.sort() |
[...arr].sort() |
| Null access | obj.prop.value |
obj?.prop?.value |
| XSS | ${userInput} in HTML |
escape(userInput) |
| SQL injection | Template literals | Parameterized queries |
Asking AI to Fix Bugs
When you find a bug, be specific:
The code has a bug: [describe bug]
Current behavior: [what happens]
Expected behavior: [what should happen]
Here's the problematic code:
```code
[paste code]
Please fix this issue while maintaining:
- Existing functionality
- Type safety
- Error handling
> **Bug Wisdom:** Most AI bugs fall into a small number of categories. Learn these patterns, and you'll catch them in seconds.
In the next lesson, we'll cover debugging strategies and when to ask AI for help.
:::