Back to Blog
debuggingai toolstroubleshootingdeveloper experienceproductivity

Debugging with AI: Modern Approaches That Actually Work

Master AI-powered debugging techniques—from root cause analysis to automated fixes for complex bugs.

B
Bootspring Team
Engineering
February 16, 2026
10 min read

Debugging is where developers spend 35-50% of their time. It's frustrating, time-consuming, and often thankless work. AI can't magically fix all bugs, but it can dramatically speed up the process—if you know how to use it effectively.

Why Traditional Debugging Is Slow#

The debugging process typically looks like:

  1. Reproduce the bug (sometimes the hardest part)
  2. Gather information (logs, stack traces, state)
  3. Form hypotheses about the cause
  4. Test each hypothesis
  5. Implement and verify the fix

Most time is spent on steps 2-4, iterating through possibilities. AI excels at accelerating these steps.

AI Debugging Strategies#

Strategy 1: Stack Trace Analysis#

Don't just paste error messages. Provide context:

1❌ Poor prompt: 2"I'm getting this error: TypeError: Cannot read property 'id' of undefined" 3 4✅ Better prompt: 5"I'm getting 'TypeError: Cannot read property 'id' of undefined' in my Next.js app. 6 7Stack trace: 8 at getUser (src/lib/users.ts:45) 9 at async UserProfile (src/app/profile/page.tsx:12) 10 at async renderPage (next/dist/server/render.js:...) 11 12The error happens when loading /profile after login. 13 14Here's the relevant code: 15[paste getUser function and UserProfile component] 16 17The user object comes from Clerk's currentUser(). 18This worked yesterday before I updated dependencies."

AI can now:

  • Identify the exact failure point
  • Understand the data flow
  • Consider recent changes
  • Suggest specific fixes

Strategy 2: Log Analysis#

AI can process log patterns humans miss:

1// Share log context with AI 2const logs = ` 3[2026-02-16 10:45:01] INFO: User login - userId: abc123 4[2026-02-16 10:45:02] INFO: Fetching user profile 5[2026-02-16 10:45:02] INFO: Fetching user orders 6[2026-02-16 10:45:02] INFO: Fetching user preferences 7[2026-02-16 10:45:03] ERROR: Database connection timeout 8[2026-02-16 10:45:03] INFO: Retry 1 - Fetching user orders 9[2026-02-16 10:45:04] ERROR: Database connection timeout 10[2026-02-16 10:45:04] INFO: Retry 2 - Fetching user orders 11[2026-02-16 10:45:05] ERROR: Database connection timeout 12[2026-02-16 10:45:05] ERROR: Failed to load user orders after 3 retries 13[2026-02-16 10:45:05] INFO: Fetching user preferences - success 14`; 15 16// AI analysis 17/* 18Pattern detected: Connection pool exhaustion 19 20Evidence: 21- Profile, orders, and preferences fetch concurrently (same timestamp) 22- Only orders fail (multiple retries at same second) 23- Preferences succeed later (pool connection freed) 24 25Likely cause: 263 concurrent queries exceed connection pool size. Orders query 27likely slower (more data), so it fails while others succeed. 28 29Suggested fixes: 301. Increase connection pool size 312. Serialize queries instead of parallel 323. Add query timeout shorter than connection timeout 33*/

Strategy 3: State Comparison#

When something "used to work," compare states:

1// Capture state when it works 2const workingState = { 3 user: { id: '123', role: 'admin', permissions: ['read', 'write'] }, 4 config: { apiVersion: 'v1', timeout: 5000 }, 5 dependencies: { 6 '@clerk/nextjs': '4.29.0', 7 'prisma': '5.10.0' 8 } 9}; 10 11// Capture state when it fails 12const failingState = { 13 user: { id: '123', role: 'admin', permissions: ['read'] }, // Missing 'write' 14 config: { apiVersion: 'v2', timeout: 5000 }, // API version changed 15 dependencies: { 16 '@clerk/nextjs': '4.30.0', // Updated 17 'prisma': '5.11.0' // Updated 18 } 19}; 20 21// AI diff analysis 22/* 23Differences found: 24 251. user.permissions: Lost 'write' permission 26 - Could be: Database migration issue, role assignment bug 27 282. config.apiVersion: Changed v1 → v2 29 - Could be: Breaking API changes, endpoint compatibility 30 313. Dependencies updated: 32 - @clerk/nextjs: Check changelog for 4.29.0 → 4.30.0 33 - prisma: Check changelog for 5.10.0 → 5.11.0 34 35Most likely culprit: API version change (affects system behavior) 36Second most likely: Missing permission (affects authorization) 37*/

Strategy 4: Reproduction Scripts#

AI can help create minimal reproductions:

1// Describe the bug 2const bugDescription = ` 3Users report that password reset emails are not being sent, 4but only for users who signed up before January 2024. 5`; 6 7// AI generates reproduction script 8const reproductionScript = ` 9// minimal-reproduction.ts 10import { sendPasswordResetEmail } from './email'; 11import { db } from './database'; 12 13async function reproduce() { 14 // Create test users 15 const oldUser = await db.user.create({ 16 data: { 17 email: 'old@test.com', 18 createdAt: new Date('2023-12-01'), // Before Jan 2024 19 } 20 }); 21 22 const newUser = await db.user.create({ 23 data: { 24 email: 'new@test.com', 25 createdAt: new Date('2024-02-01'), // After Jan 2024 26 } 27 }); 28 29 // Test both 30 console.log('Testing old user...'); 31 const oldResult = await sendPasswordResetEmail(oldUser.email); 32 console.log('Old user result:', oldResult); 33 34 console.log('Testing new user...'); 35 const newResult = await sendPasswordResetEmail(newUser.email); 36 console.log('New user result:', newResult); 37} 38 39reproduce(); 40`; 41 42// Running this might reveal: 43// Old user result: { sent: false, error: 'Invalid email format' } 44// New user result: { sent: true } 45// 46// Hypothesis: Email validation changed, old emails in different format

Strategy 5: Binary Search Debugging#

For regressions, AI can guide git bisect:

1# AI helps structure the bisect 2git bisect start 3git bisect bad HEAD 4git bisect good v1.2.0 5 6# AI generates test script 7cat > test-bug.sh << 'EOF' 8#!/bin/bash 9npm install --silent 10npm run build --silent 11npm run test:specific -- --grep "password reset" 12exit $? 13EOF 14 15git bisect run ./test-bug.sh 16 17# AI analyzes the result 18# "Bug introduced in commit abc123: 'Refactored email validation' 19# This commit changed the regex for email validation. 20# Old format emails (without +tags) now fail validation."

Advanced AI Debugging Techniques#

Technique 1: Hypothesis Generation#

Ask AI to generate multiple hypotheses:

1Prompt: 2"My API endpoint returns 500 errors randomly, about 10% of requests. 3No pattern in time of day or user type. 4Same request succeeds on retry. 5Give me 5 possible causes ranked by likelihood." 6 7AI response: 81. Race condition (70% likely) 9 - Concurrent access to shared state 10 - Test: Add request IDs, correlate with logs 11 122. Connection pool exhaustion (60% likely) 13 - Database or external service connection limits 14 - Test: Monitor connection pool metrics 15 163. Memory pressure (40% likely) 17 - GC pauses or OOM conditions 18 - Test: Add memory monitoring, check for leaks 19 204. External service flakiness (30% likely) 21 - Third-party API intermittent failures 22 - Test: Add detailed timing logs for external calls 23 245. Load balancer issues (20% likely) 25 - Unhealthy instance in rotation 26 - Test: Check load balancer health checks

Technique 2: Code Path Tracing#

AI can trace execution paths:

1// Ask AI to trace a specific scenario 2const scenario = ` 3User clicks "Submit Order" but order is not created. 4No error shown to user. No error in logs. 5Payment is charged. 6`; 7 8// AI traces the code path 9/* 10Expected flow: 111. handleSubmit() in OrderForm.tsx 122. createOrder() in /api/orders/route.ts 133. processPayment() in /lib/stripe.ts 144. saveOrder() in /lib/orders.ts 155. sendConfirmation() in /lib/email.ts 16 17Possible failure points: 18- Step 2-3: Payment succeeds but order creation throws 19- Step 3-4: saveOrder fails silently (check error handling) 20- Step 4-5: Order saved but confirmation fails 21 22Code review findings: 23In /lib/orders.ts line 45:

try { await db.order.create(data); } catch (error) { // BUG: Error swallowed, no re-throw console.error(error); }

This explains why payment works but order isn't saved - the error is caught and logged but not propagated. */

Technique 3: Automated Fix Suggestions#

AI can propose fixes with explanations:

1// Bug: Race condition in counter 2const buggyCode = ` 3let counter = 0; 4 5async function incrementCounter() { 6 const current = counter; 7 await someAsyncOperation(); 8 counter = current + 1; 9} 10`; 11 12// AI fix with explanation 13const fix = { 14 code: ` 15import { Mutex } from 'async-mutex'; 16 17const mutex = new Mutex(); 18let counter = 0; 19 20async function incrementCounter() { 21 const release = await mutex.acquire(); 22 try { 23 const current = counter; 24 await someAsyncOperation(); 25 counter = current + 1; 26 } finally { 27 release(); 28 } 29} 30`, 31 explanation: ` 32The bug occurs because: 331. Two calls read 'counter' simultaneously (both get 0) 342. Both do async work 353. Both set counter to 1 (should be 2) 36 37The fix uses a mutex to ensure only one increment runs at a time. 38Alternative approaches: 39- Use atomic increment if available 40- Use database transactions for persistence 41- Use a queue for sequential processing 42`, 43 testCase: ` 44it('handles concurrent increments', async () => { 45 counter = 0; 46 await Promise.all([ 47 incrementCounter(), 48 incrementCounter(), 49 incrementCounter() 50 ]); 51 expect(counter).toBe(3); 52}); 53` 54};

Building a Debugging Workflow#

Step 1: Gather Context#

1const debugContext = { 2 error: captureError(), 3 stackTrace: getStackTrace(), 4 logs: getRecentLogs(100), 5 state: captureApplicationState(), 6 recentChanges: getGitDiff('HEAD~5'), 7 environment: getEnvironmentInfo(), 8 timing: getRequestTiming() 9};

Step 2: Ask AI for Analysis#

1Analyze this bug with the following context: 2[paste debugContext] 3 4Please provide: 51. Most likely root cause 62. Additional information needed 73. Suggested debugging steps 84. Potential fixes (if cause is clear)

Step 3: Iterate#

Follow-up: "I checked the database connections and pool size is 10. Peak concurrent queries logged was 8. However, I noticed queries to the orders table take 2-3 seconds. What should I check next?"

Step 4: Verify Fix#

1// AI helps generate verification tests 2const verificationTests = [ 3 { 4 name: 'Bug does not reproduce', 5 test: async () => { 6 // Original reproduction steps 7 const result = await triggerBugScenario(); 8 expect(result.error).toBeUndefined(); 9 } 10 }, 11 { 12 name: 'Fix does not introduce regression', 13 test: async () => { 14 // Related functionality still works 15 await runRelatedTests(); 16 } 17 }, 18 { 19 name: 'Performance is acceptable', 20 test: async () => { 21 const timing = await measurePerformance(); 22 expect(timing.p99).toBeLessThan(100); 23 } 24 } 25];

Common Debugging Scenarios#

Scenario 1: "It Works on My Machine"#

1Prompt: 2"This code works locally but fails in production: 3[code] 4 5Local: macOS, Node 20, Postgres 15 6Production: Linux, Node 18, Postgres 14 7 8What could cause the difference?" 9 10AI identifies: 11- Node version differences (check for v20-specific features) 12- PostgreSQL version (check for syntax/function differences) 13- Environment variables (may differ) 14- File paths (case sensitivity on Linux) 15- Timezone handling (server vs local)

Scenario 2: Memory Leak#

1Prompt: 2"Our Node.js app's memory usage grows 10MB/hour until OOM. 3No obvious leaks in our code. Using Express, Prisma, Redis. 4Heap snapshots show increasing 'String' allocations." 5 6AI suggests: 71. Check for event listener accumulation 82. Look for unclosed database connections 93. Review caching without expiration 104. Check for closure-held references 115. Examine third-party library issues 12 13Specific checks: 14- Redis client connection handling 15- Prisma connection pooling settings 16- Express middleware chain

Scenario 3: Intermittent Failure#

1Prompt: 2"This test fails ~20% of the time in CI but never locally: 3[test code] 4 5What are common causes of flaky tests?" 6 7AI identifies patterns: 81. Timing dependencies (use waitFor, not sleep) 92. Test order dependencies (ensure isolation) 103. Shared state between tests (reset state) 114. Race conditions in async code (proper await usage) 125. Environment differences (CI resource constraints)

Tools That Help#

ToolUse CaseAI Integration
SentryError trackingAI analysis of trends
DataDogAPM and logsAI anomaly detection
Chrome DevToolsFrontend debuggingLimited
VS Code DebuggerStep debuggingCopilot integration
PostmanAPI debuggingAI test generation

Conclusion#

AI doesn't debug for you—it debugs with you. The key is providing rich context and asking specific questions. Treat AI as a knowledgeable colleague who hasn't seen your codebase before: explain the situation thoroughly, and you'll get better help.


Bootspring's AI agents include debugging assistance that understands your full codebase. Debug faster with context-aware help.

Share this article

Help spread the word about Bootspring