Debugging with Claude Code: Advanced Techniques
Move beyond basic error messages. Learn how to leverage the debugger agent, test-runner, and parallel investigation for systematic root cause analysis.
Debugging is where Claude Code truly shines. Instead of manually tracing through code, you can leverage Claude’s ability to understand context, analyze patterns, and reason about behavior—with specialized agents designed specifically for debugging.
This guide covers debugging subagents, the Agent tool for parallel investigation, and advanced techniques that go beyond “fix this error.”
Updated October 21, 2026: Switched the examples to the
Agenttool and current models, noted thatdebuggerandtest-runnerare custom subagents you define (the built-ins are Explore, Plan, and general-purpose), corrected Explore’s model and the task-list tools’ availability, and added the/debugcommand.
Official Debugging Tools
The debugger Agent
Claude Code’s built-in subagents are Explore, Plan, and general-purpose; debugger is a custom subagent you define in .claude/agents/debugger.md for systematic root cause analysis. For a built-in starting point, run /debug, the bundled skill that turns on debug logging for the session and investigates from the log.
---
name: debugger
description: Investigates errors and test failures to find the root cause. Use for stack traces and unexpected behavior.
tools: Read, Glob, Grep, Bash
model: sonnet
---
You are a debugger. Reproduce the problem, trace it to its root cause,
and propose the smallest fix that addresses the cause rather than the symptom.
Claude then delegates to it through the Agent tool (named Task before v2.1.63; Task(...) still works as an alias):
Agent({
subagent_type: "debugger",
model: "sonnet",
prompt: `
Investigate: TypeError: Cannot read property 'id' of undefined
at CheckoutForm.handleSubmit (checkout.tsx:45)
Context: Error occurs when submitting checkout with empty cart.
Find root cause and suggest fix.
`
})
When to use debugger agent:
- Error investigation requiring deep analysis
- Root cause analysis for complex bugs
- Systematic tracing through multiple files
- Understanding unexpected behavior
The test-runner Agent
The test-runner agent is another custom subagent; it validates fixes and ensures no regressions:
Agent({
subagent_type: "test-runner",
model: "haiku",
prompt: `
Run tests related to checkout functionality.
Analyze any failures and report coverage gaps.
`
})
When to use test-runner agent:
- After implementing fixes
- To verify reproduction tests pass
- To check for regression coverage
- To analyze test coverage gaps
The Explore Agent for Bug Hunting
Explore is a built-in, read-only agent that excels at rapid codebase investigation: Write and Edit are denied to it. By default it runs on your main conversation’s model (when that is Fable, it runs on the model the opus alias resolves to). A model passed with the call takes precedence, so the examples below keep exploration on Haiku; defining your own Explore agent in .claude/agents/ overrides the built-in for every call.
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: `
Explore authentication module (thoroughness: medium).
Find all places where user session might be null.
`
})
Thoroughness levels: Claude passes quick for targeted lookups, medium for balanced exploration, or very thorough for comprehensive analysis.
| Level | Use Case |
|---|---|
quick | Find a specific error pattern |
medium | Map related code paths |
very thorough | Complete flow analysis |
The Debugging Mindset Shift
Traditional Debugging
1. See error
2. Google error message
3. Try random Stack Overflow solutions
4. Add console.log statements
5. Repeat until fixed
Claude Code Debugging
1. See error
2. Launch parallel investigation agents
3. Let agents trace the root cause
4. Understand why it happened
5. Fix properly with test-runner verification
The difference: Claude doesn’t just fix the symptom—it understands the disease.
Technique 1: Context-Rich Error Reporting
Don’t just paste the error. Give Claude the full story.
Bad Approach
"Fix this error: TypeError: Cannot read property 'id' of undefined"
Good Approach
"I'm getting this error when submitting the checkout form:
Error: TypeError: Cannot read property 'id' of undefined
at CheckoutForm.handleSubmit (checkout.tsx:45)
at processOrder (orders.ts:123)
at <anonymous>
What I was doing:
- Logged in as test user
- Added 2 items to cart
- Clicked submit on checkout
What I expected:
- Order to be created
- Redirect to confirmation page
The error started after I merged PR #234 yesterday.
Relevant recent changes: Updated cart state management."
Why This Works
Claude can now:
- Trace the stack to find the origin
- Consider recent changes as suspects
- Understand the expected behavior
- Reproduce the scenario mentally
Technique 2: Parallel Investigation with the Agent Tool
From the official subagents documentation, use multi-agent analysis for complex bugs. Send the calls in one message so they run concurrently:
// Launch 5 parallel investigation agents
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Search for session/cookie handling changes this week (thoroughness: quick)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Analyze authentication middleware patterns (thoroughness: medium)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Check for race conditions in auth state (thoroughness: quick)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Review error logs for auth-related errors (thoroughness: quick)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Find timeout/expiry configuration changes (thoroughness: quick)"
})
Time comparison:
- Sequential investigation: 5 × 30s = 150 seconds
- Parallel investigation: max(30s) = 30 seconds
- Best-case example: about one fifth of the serial wall-clock time, before startup and coordination overhead
Each agent focuses on one hypothesis. The first to find strong evidence guides the investigation.
Technique 3: The Debugger-Test Runner Workflow
Combine debugger and test-runner agents for comprehensive debugging:
Phase 1 - Investigation (debugger agent):
→ Analyze error and stack trace
→ Identify root cause
→ Propose fix
Phase 2 - Verification (test-runner agent):
→ Run existing tests
→ Verify fix doesn't break other functionality
→ Suggest additional test coverage
Phase 3 - Regression Prevention:
→ Create reproduction test
→ Ensure test fails without fix
→ Ensure test passes with fix
Implementation:
// Phase 1: debugger investigates
Agent({
subagent_type: "debugger",
model: "sonnet",
prompt: `
Investigate checkout failure.
Error: TypeError at checkout.tsx:45
Find root cause and propose fix.
`
})
// Phase 2: test-runner verifies (after fix)
Agent({
subagent_type: "test-runner",
model: "haiku",
prompt: `
Run all checkout-related tests.
Report any failures and coverage analysis.
`
})
Technique 4: Behavioral Analysis
When you know something is wrong but can’t pinpoint it.
"Something's wrong with the search feature. Results seem off.
Behavior I'm seeing:
- Search for 'javascript' returns Python articles
- Exact title matches don't appear first
- Results change on page refresh (shouldn't happen)
Help me understand:
1. What search algorithm are we using?
2. Where is the ranking logic?
3. What could cause non-deterministic results?
4. How can we add debugging to trace a query?"
Claude will:
- Map the search pipeline
- Identify potential issues at each stage
- Suggest instrumentation points
- Help create a debugging plan
Technique 5: Regression Hunting with Git Integration
When something that worked suddenly doesn’t:
"The export feature broke. It was working on Friday.
git log shows these changes since Friday:
- abc123: Updated PDF library
- def456: Refactored file service
- ghi789: Added new export format
Help me:
1. Identify which commit most likely caused the regression
2. Explain what each change does
3. Suggest how to verify the culprit
4. Provide a fix if you can identify the issue"
Parallel analysis approach:
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Analyze commit abc123 impact on export feature (thoroughness: quick)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Analyze commit def456 impact on export feature (thoroughness: quick)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Analyze commit ghi789 impact on export feature (thoroughness: quick)"
})
Technique 6: Error Pattern Analysis
For recurring or related errors:
"We're seeing multiple related errors in production:
1. TypeError: Cannot read 'user' of null (dashboard.tsx)
2. TypeError: Cannot read 'profile' of null (settings.tsx)
3. TypeError: Cannot read 'preferences' of null (notifications.tsx)
All involve user data. What's the common cause?
Why might user be null in these places?"
Claude will:
- Identify the shared pattern (user data access)
- Trace the user data flow
- Find where the null originates
- Suggest a systematic fix
Technique 7: Performance Debugging
When things are slow, use parallel profiling:
// Launch parallel performance investigation
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Find N+1 query patterns in dashboard data fetching (thoroughness: medium)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Identify waterfall request patterns in API calls (thoroughness: medium)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Find unnecessary re-renders in React components (thoroughness: quick)"
})
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: "Check for missing database indexes on slow queries (thoroughness: quick)"
})
Technique 8: State Debugging
For complex state management issues:
"The shopping cart state is getting corrupted.
Symptoms:
- Items appear/disappear randomly
- Quantities reset to 1
- Total doesn't match items
We use Redux Toolkit. Cart slice is in store/cart.ts.
I suspect a race condition but can't reproduce it consistently.
Help me trace where state mutations might be happening incorrectly."
Claude will:
- Analyze the cart reducer
- Find potential mutation issues
- Identify race conditions in async actions
- Suggest state debugging tools
Debugging Workflow with Subagents
Step 1: Gather Context and Launch Investigation
// Launch parallel investigation
Agent({
subagent_type: "Explore",
model: "haiku",
prompt: `
Explore error context (thoroughness: medium).
Find all files related to: [error location]
Map data flow and dependencies.
`
})
Step 2: Deep Analysis with debugger Agent
Agent({
subagent_type: "debugger",
model: "sonnet",
prompt: `
Context from exploration: [results]
Error: [full stack trace]
Perform root cause analysis:
1. Trace execution path
2. Identify failure point
3. Determine fix
`
})
Step 3: Verify with test-runner Agent
Agent({
subagent_type: "test-runner",
model: "haiku",
prompt: `
After fix applied to [files]:
1. Run related tests
2. Check for regressions
3. Report coverage
`
})
Step 4: Prevent Regression
After identifying the cause:
- Understand WHY it happened
- Fix the root cause, not just the symptom
- Add a test to prevent regression
- Check for similar issues elsewhere
Common Debugging Patterns
The Null Reference Pattern
Error: Cannot read property 'X' of undefined
Questions to ask:
- Where should X come from?
- What conditions make it undefined?
- Is there a race condition?
- Is there a missing initialization?
The Async Timing Pattern
Symptoms: Intermittent failures, works sometimes
Questions to ask:
- Are there race conditions?
- Are promises handled correctly?
- Is there missing await?
- Are there timing assumptions?
The State Mutation Pattern
Symptoms: UI doesn't update, stale data
Questions to ask:
- Is state being mutated directly?
- Are immutability rules followed?
- Are dependencies in useEffect correct?
- Is memoization working correctly?
The Integration Pattern
Symptoms: Works locally, fails in production
Questions to ask:
- Are environment variables correct?
- Are URLs/endpoints correct?
- Are there network/CORS issues?
- Are there timeout differences?
Model Selection for Debugging
From the Claude Code model configuration docs:
| Task | Recommended Model | Why |
|---|---|---|
| Quick file search | Haiku 5.5 | Fast, cheap |
| Pattern matching | Haiku 5.5 | Fast, cheap |
| Root cause analysis | Sonnet 5.5 | Balanced reasoning |
| Complex debugging | Opus 5.5 | The default model; raise effort with /effort high |
| Critical bug fix | Fable 5.1 | Highest intelligence, best for long investigations |
Opus 5.5, Sonnet 5.5, and Haiku 5.5 run at medium effort by default, so a stubborn bug is often a case for /effort high or xhigh rather than a different model. max is the deepest level and applies to the current session only.
Quick model switching (v2.0.65+): Press Option+P (macOS) or Alt+P (Windows/Linux) during prompting.
Real-World Example: Bug Investigation
User: "Production error: 'Payment failed' but money was charged."
Parallel investigation (5 Explore agents):
→ Search payment logs for error pattern
→ Analyze payment service error handling
→ Check Stripe webhook handlers
→ Review recent payment changes
→ Find similar issues in error tracking
Results:
- Agent 3 finds: Webhook handler doesn't retry on timeout
- Agent 4 confirms: Recent change added new timeout logic
- Agent 1 shows: Pattern started after deploy on Jan 5
Root cause identified in ~1 minute vs 10+ sequential.
Getting Started
Today:
- Run
/debugon your next bug, then write adebuggersubagent for the follow-up - Use parallel Explore agents for investigation
- Verify fixes with test-runner agent
This week:
- Develop a debugging prompt template
- Use parallel investigation for complex bugs
- Create reproduction tests for every fix
This month:
- Build debugging patterns for your common issues
- Integrate debugger + test-runner workflow
- Share patterns with your team
The goal isn’t just to fix bugs faster—it’s to understand your codebase better through each debugging session.
Sources: Claude Code Documentation, Subagents, Commands, Model configuration, Claude Code GitHub