Intermediate35 min1 prerequisite

Master debugging techniques for AI-generated code, including common patterns, error diagnosis, and systematic fixing approaches.

Debugging AI-Generated Code

Learn systematic approaches to debug AI-generated code, identify common issues, and fix problems efficiently.

Why Debugging AI Code is Different

Common Patterns

Terminal
AI-Generated Code Issues:
├── Hallucinated APIs
   └── Functions/methods that don't exist
├── Version Mismatches
   └── Code for older/newer library versions
├── Missing Dependencies
   └── Imports without installation
├── Context Errors
   └── Code that ignores existing patterns
├── Incomplete Logic
   └── Edge cases not handled
└── Copy-Paste Artifacts
    └── Placeholder values, example data

Debugging Mindset

Terminal
Traditional: "The code is probably correct"
AI-Assisted: "The code might have subtle issues"

Key difference:
- AI generates plausible-looking code
- It may compile but behave unexpectedly
- Always verify against documentation

Phase 1: Error Classification

Build/Compile Errors

Errors that prevent the code from running:

Terminal
// Common AI mistake: Wrong import path
// AI generated:
import { Button } from '@/ui/button'

// Actual path:
import { Button } from '@/components/ui/button'

How to fix:

  1. Read the exact error message
  2. Check actual file paths
  3. Verify package is installed

Runtime Errors

Errors that occur during execution:

Terminal
// AI generated code assuming data exists
const userName = user.profile.name

// Reality: user.profile might be null
// Fix:
const userName = user?.profile?.name ?? 'Anonymous'

How to fix:

  1. Check browser console or terminal
  2. Add null/undefined checks
  3. Validate data shapes

Logic Errors

Code runs but produces wrong results:

Terminal
// AI generated: Off-by-one error
for (let i = 0; i <= array.length; i++) {
  // Accesses array[array.length] = undefined
}

// Fix:
for (let i = 0; i < array.length; i++) {
  // Correct bounds
}

How to fix:

  1. Add console.log statements
  2. Use debugger breakpoints
  3. Test with edge cases

Phase 2: Debugging Workflow

Step 1: Reproduce the Error

Terminal
1. Note exact steps to trigger error
2. Check if error is consistent
3. Identify the smallest reproducible case

Example notes:
"Error occurs when:
- Click submit button
- Form has empty email field
- Only on first attempt"

Step 2: Read Error Messages

Terminal
# Terminal error example:
TypeError: Cannot read properties of undefined (reading 'map')
    at ProductList (./components/ProductList.tsx:15:23)

# Key information:
# - Error type: TypeError
# - Problem: Trying to use .map() on undefined
# - Location: ProductList.tsx, line 15

Step 3: Isolate the Problem

Terminal
// Original AI-generated code
export async function getProducts() {
  const response = await fetch('/api/products')
  const data = await response.json()
  return data.products.map(p => ({ ...p, price: p.price / 100 }))
}

// Add debugging
export async function getProducts() {
  const response = await fetch('/api/products')
  console.log('Response status:', response.status)

  const data = await response.json()
  console.log('Data received:', data)
  console.log('Products array:', data.products)

  if (!data.products) {
    console.error('No products in response:', data)
    return []
  }

  return data.products.map(p => ({ ...p, price: p.price / 100 }))
}

Step 4: Fix and Verify

Terminal
// Apply fix based on findings
export async function getProducts() {
  try {
    const response = await fetch('/api/products')

    if (!response.ok) {
      throw new Error(`HTTP error: ${response.status}`)
    }

    const data = await response.json()

    // Handle different response shapes
    const products = data.products ?? data ?? []

    return products.map(p => ({
      ...p,
      price: typeof p.price === 'number' ? p.price / 100 : 0
    }))
  } catch (error) {
    console.error('Failed to fetch products:', error)
    return []
  }
}

Phase 3: Common AI Code Issues

Issue 1: Hallucinated APIs

Terminal
// AI generated (doesn't exist)
const { data } = await supabase
  .from('users')
  .selectOne('*')  // Not a real method!
  .eq('id', userId)

// Actual Supabase API
const { data } = await supabase
  .from('users')
  .select('*')
  .eq('id', userId)
  .single()

Fix approach:

  1. Check official documentation
  2. Use TypeScript for autocomplete
  3. Verify method signatures

Issue 2: Version Mismatches

Terminal
// AI generated for Next.js 13 App Router
// But project uses Pages Router

// App Router pattern (AI generated)
// app/api/users/route.ts
export async function GET(request: Request) {
  return Response.json({ users: [] })
}

// Pages Router pattern (what's needed)
// pages/api/users.ts
export default function handler(req, res) {
  res.status(200).json({ users: [] })
}

Fix approach:

  1. Check project's framework version
  2. Look at existing code patterns
  3. Update prompt with version info

Issue 3: Missing Error Handling

Terminal
// AI generated (happy path only)
async function saveUser(userData) {
  const user = await db.users.create(userData)
  redirect('/dashboard')
}

// With proper error handling
async function saveUser(userData) {
  try {
    const user = await db.users.create(userData)
    redirect('/dashboard')
  } catch (error) {
    if (error.code === 'P2002') {
      return { error: 'Email already exists' }
    }
    console.error('Failed to save user:', error)
    return { error: 'Something went wrong' }
  }
}

Issue 4: Hardcoded Values

Terminal
// AI generated with placeholder values
const API_KEY = 'sk-your-api-key-here'
const DATABASE_URL = 'postgresql://user:pass@localhost:5432/db'

// Should use environment variables
const API_KEY = process.env.API_KEY
const DATABASE_URL = process.env.DATABASE_URL

Issue 5: Incomplete Type Safety

Terminal
// AI generated with any types
function processData(data: any): any {
  return data.items.map((item: any) => item.value)
}

// Properly typed
interface DataItem {
  value: number
  label: string
}

interface DataResponse {
  items: DataItem[]
}

function processData(data: DataResponse): number[] {
  return data.items.map(item => item.value)
}

Phase 4: Debugging Tools

Browser DevTools

Terminal
Console Tab:
- View console.log output
- See JavaScript errors
- Execute code in context

Network Tab:
- Inspect API requests/responses
- Check status codes
- View response data

Sources Tab:
- Set breakpoints
- Step through code
- Inspect variables

VS Code / Cursor Debugger

Terminal
// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "npm",
      "runtimeArgs": ["run", "dev"],
      "skipFiles": ["<node_internals>/**"],
      "env": {
        "NODE_OPTIONS": "--inspect"
      }
    }
  ]
}

React DevTools

Terminal
Components Tab:
- Inspect component tree
- View props and state
- Edit values in real-time

Profiler Tab:
- Record renders
- Find performance issues
- Identify unnecessary re-renders

TypeScript Compiler

Terminal
# Check for type errors
npx tsc --noEmit

# With stricter checking
npx tsc --noEmit --strict

Phase 5: Debugging Prompts

Ask AI to Debug

Terminal
"This code throws an error: [paste error message]

Here's the code:
[paste code]

What's causing the error and how do I fix it?"

Ask AI to Explain

Terminal
"Explain what this code does step by step:
[paste code]

I'm confused about [specific part]."

Ask for Alternative Approaches

Terminal
"This code isn't working as expected:
[paste code]

Expected behavior: [describe]
Actual behavior: [describe]

Can you suggest a different approach?"

Provide Context

Terminal
"I'm using:
- Next.js 15 with App Router
- Supabase for database
- TypeScript

This code should [describe goal] but instead [describe problem]:
[paste code]"

Phase 6: Prevention Strategies

Before Accepting AI Code

Terminal
Checklist:
 Read through the entire code
 Understand what each part does
 Check imports are correct
 Verify APIs/methods exist
 Look for hardcoded values
 Check error handling
 Test edge cases mentally

Better Prompts

Terminal
Good prompt structure:
1. Context (framework, versions)
2. Goal (what you want to achieve)
3. Constraints (patterns to follow)
4. Examples (existing code patterns)

Example:
"Using Next.js 15 App Router with TypeScript and Supabase,
create an API route to fetch user data.
Follow the existing pattern in app/api/products/route.ts.
Include proper error handling and types."

Incremental Development

Terminal
Instead of:
"Build a complete e-commerce checkout system"

Do:
1. "Create a cart context"
2. "Add function to calculate totals"
3. "Create checkout API route"
4. "Build checkout form UI"
5. "Connect form to API"

Real-World Debugging Session

Scenario: Form Not Submitting

Terminal
// AI-generated code
export function ContactForm() {
  async function handleSubmit(formData: FormData) {
    'use server'
    const email = formData.get('email')
    await sendEmail(email)
  }

  return (
    <form action={handleSubmit}>
      <input name="email" type="email" />
      <button type="submit">Send</button>
    </form>
  )
}

Problem: Nothing happens when clicking submit.

Debugging Steps

  1. Check console: No errors
  2. Check network: No request made
  3. Inspect code: Server Action looks correct
  4. Check imports: sendEmail not imported!
Terminal
// Fixed code
import { sendEmail } from '@/lib/email'

export function ContactForm() {
  async function handleSubmit(formData: FormData) {
    'use server'
    const email = formData.get('email') as string

    if (!email) {
      throw new Error('Email required')
    }

    await sendEmail(email)
  }

  return (
    <form action={handleSubmit}>
      <input name="email" type="email" required />
      <button type="submit">Send</button>
    </form>
  )
}

Verification Checklist

  • Can identify error type (build/runtime/logic)
  • Know how to read error messages
  • Can isolate problems systematically
  • Familiar with browser DevTools
  • Can write effective debugging prompts
  • Understand common AI code issues
  • Apply prevention strategies

Quick Reference

Error Type → First Action

Error TypeFirst Action
Import errorCheck file paths and package installation
Type errorCheck function signatures and types
Runtime null errorAdd optional chaining (?.)
API errorCheck network tab, verify endpoint
State not updatingCheck React state rules
Style not applyingCheck class names, inspect element

Debugging Commands

Terminal
# Check for TypeScript errors
npx tsc --noEmit

# Check for ESLint issues
npm run lint

# Clear Next.js cache
rm -rf .next

# Reinstall dependencies
rm -rf node_modules && npm install

# Check package versions
npm list [package-name]

Summary

Key debugging strategies:

  • Classify the error type first
  • Read error messages carefully
  • Isolate the problem systematically
  • Verify against documentation
  • Test edge cases
  • Prevent issues with better prompts

Next Steps

Explore advanced topics like multi-tool workflows and enterprise patterns.

Mark this lesson as complete to track your progress