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.
:::

Quiz

Module 5: Debugging AI-Generated Code

Take Quiz