- Learn
- Guided Projects
- Debugging AI-Generated Code
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:
- Read the exact error message
- Check actual file paths
- 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:
- Check browser console or terminal
- Add null/undefined checks
- 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:
- Add console.log statements
- Use debugger breakpoints
- 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:
- Check official documentation
- Use TypeScript for autocomplete
- 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:
- Check project's framework version
- Look at existing code patterns
- 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
- Check console: No errors
- Check network: No request made
- Inspect code: Server Action looks correct
- Check imports:
sendEmailnot 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 Type | First Action |
|---|---|
| Import error | Check file paths and package installation |
| Type error | Check function signatures and types |
| Runtime null error | Add optional chaining (?.) |
| API error | Check network tab, verify endpoint |
| State not updating | Check React state rules |
| Style not applying | Check 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