bug-hunter
npx skills add https://github.com/xkayo32/agent-memory-orchestrator --skill bug-hunter
Agent 安装分布
Skill 文档
Bug Hunter: Debugging & Root Cause Analysis
Purpose
Systematically investigate errors, diagnose problems, identify root causes, and propose fixes through methodical debugging approaches.
When to Use This Role
â USE when:
- Application presents errors
- Unexpected behavior occurs
- Tests fail without clear reason
- Performance degrades
- Need root cause analysis
â DO NOT USE when:
- Implementing new feature (use implementer)
- Error is obvious with clear fix (fix directly)
- Writing preventive tests (use tester)
- Design decisions needed (use architect)
Debugging Methodology
1. Reproduction
Establish consistent reproduction steps:
Reproduction checklist:
- Can error be reproduced consistently?
- What are exact steps to trigger?
- Does it happen in specific environment only?
- Is there a stack trace or error log?
- What changed since it last worked?
Document reproduction:
Steps to Reproduce:
1. Start application: npm start
2. Navigate to /login
3. Enter valid credentials
4. Click login button
5. Observe: "TypeError: Cannot read property 'token' of undefined"
Environment:
- OS: macOS 14.1
- Node: 18.17.0
- Browser: Chrome 120
Frequency: 100% (every login attempt)
2. Isolation
Narrow down the problem source:
Isolation techniques:
Binary Search:
Disable half the code/features
Problem still occurs?
Yes: Problem is in enabled half
No: Problem is in disabled half
Repeat until isolated
Strategic Logging:
console.log('[DEBUG] Input:', input)
console.log('[DEBUG] After transformation:', transformed)
console.log('[DEBUG] Before validation:', data)
console.log('[DEBUG] Final result:', result)
Debugging Tools:
// Breakpoint in code
debugger; // Execution pauses here
// Conditional breakpoint
if (userId === 'problematic-id') {
debugger;
}
Git Bisect:
# Find commit that introduced bug
git bisect start
git bisect bad # Current commit is broken
git bisect good v1.0.0 # v1.0.0 was working
# Git tests commits, you mark good/bad
# Until culprit commit found
3. Diagnosis
Analyze to find root cause:
Questions to ask:
- What changed since last working version?
- Which files were modified?
- Were dependencies updated?
- Is it logic error, state issue, or environment?
- Are there assumptions that don’t hold?
Stack Trace Analysis:
Error: Cannot read property 'name' of undefined
at getUserName (user.service.ts:42)
at renderProfile (profile.component.tsx:18)
at onClick (button.component.tsx:10)
Analysis:
1. Button clicked â button.component:10
2. Calls renderProfile â profile.component:18
3. Calls getUserName â user.service:42
4. Tries to access user.name but user is undefined
Root Cause: getUserName() returns undefined when user not in cache
Fix: Add null check or fetch user if not cached
4. Fix & Verification
Fix root cause, not symptoms:
Fix principles:
- Address root cause, not just symptoms
- Add test to prevent regression
- Document why problem occurred
- Verify fix doesn’t break anything else
Verification steps:
- Implement fix
- Verify original issue resolved
- Run full test suite
- Check for side effects
- Test in same environment where bug occurred
Common Debugging Patterns
Pattern 1: Add Logging
// Before (mysterious failure)
function processUser(userId: string) {
const user = getUser(userId)
return user.profile.avatar
}
// After (reveals problem)
function processUser(userId: string) {
console.log('[DEBUG] Input userId:', userId)
const user = getUser(userId)
console.log('[DEBUG] Retrieved user:', user)
if (!user) {
console.error('[DEBUG] User not found!')
throw new NotFoundError(`User ${userId} not found`)
}
console.log('[DEBUG] User profile:', user.profile)
if (!user.profile) {
console.error('[DEBUG] User has no profile!')
throw new Error(`User ${userId} has no profile`)
}
return user.profile.avatar
}
Pattern 2: Inspect State
// Debug React state issues
useEffect(() => {
console.log('[STATE] userId:', userId)
console.log('[STATE] user:', user)
console.log('[STATE] isLoading:', isLoading)
console.log('[STATE] error:', error)
}, [userId, user, isLoading, error])
Pattern 3: Isolate with Unit Test
// Reproduce issue in isolated test
it('should handle missing user gracefully', () => {
const mockDb = {
findUser: jest.fn().mockResolvedValue(null)
}
const service = new UserService(mockDb)
// This should throw NotFoundError, but crashes instead
expect(() => service.getUserName('missing-id'))
.toThrow(NotFoundError)
})
Pattern 4: Check Assumptions
// Assumption: req.user always exists after auth middleware
function getProfile(req, res) {
// DEBUG: Validate assumption
console.assert(req.user, 'req.user should exist after auth')
if (!req.user) {
console.error('[DEBUG] req.user is undefined!')
console.error('[DEBUG] req.headers:', req.headers)
console.error('[DEBUG] req.cookies:', req.cookies)
throw new Error('User not authenticated')
}
return res.json(req.user.profile)
}
Debugging Tools & Techniques
Console Logging
// Structured logging
console.log('[MODULE:FUNCTION] Variable:', value)
console.log('[UserService:login] Credentials:', { email, hasPassword: !!password })
// Object inspection
console.dir(complexObject, { depth: null })
// Table view for arrays
console.table(users)
// Performance timing
console.time('database-query')
await db.query(...)
console.timeEnd('database-query')
Debugger Statements
// Pause execution
function complexCalculation(input) {
debugger; // Execution pauses, can inspect variables
const step1 = transform(input)
debugger; // Check step1 value
const step2 = validate(step1)
debugger; // Check step2 value
return step2
}
Network Inspection
// Log HTTP requests
fetch('/api/users')
.then(res => {
console.log('[DEBUG] Response status:', res.status)
console.log('[DEBUG] Response headers:', res.headers)
return res.json()
})
.then(data => {
console.log('[DEBUG] Response data:', data)
})
.catch(error => {
console.error('[DEBUG] Request failed:', error)
})
Database Query Logging
// Log SQL queries
db.on('query', (query) => {
console.log('[DB] Query:', query.sql)
console.log('[DB] Params:', query.bindings)
console.log('[DB] Duration:', query.duration + 'ms')
})
Example Debugging Session
Problem: “Login always fails with ‘Invalid token'”
1. Reproduction
Steps:
1. POST /api/login with valid credentials
2. Receive 200 OK with token
3. POST /api/profile with token in Authorization header
4. Receive 401 Unauthorized: "Invalid token"
Consistent: Yes, 100% reproduction
2. Isolation
Added logging to middleware:
// auth.middleware.ts
export function requireAuth(req, res, next) {
console.log('[AUTH] Headers:', req.headers)
const authHeader = req.headers.authorization
console.log('[AUTH] Auth header:', authHeader)
if (!authHeader) {
console.log('[AUTH] No auth header!')
return res.status(401).json({ error: 'No token' })
}
const token = authHeader.split(' ')[1]
console.log('[AUTH] Extracted token:', token)
const decoded = verifyToken(token)
console.log('[AUTH] Decoded:', decoded)
if (!decoded) {
console.log('[AUTH] Token verification failed!')
return res.status(401).json({ error: 'Invalid token' })
}
req.user = decoded
next()
}
Output:
[AUTH] Headers: { authorization: 'Bearer undefined' }
[AUTH] Auth header: Bearer undefined
[AUTH] Extracted token: undefined
[AUTH] Decoded: null
[AUTH] Token verification failed!
3. Diagnosis
Token is undefined in Authorization header!
Checked login response:
// auth.controller.ts
export async function login(req, res) {
const token = generateToken(user.id, user.email)
console.log('[LOGIN] Generated token:', token) // Token exists!
res.json({
message: 'Login successful',
access_token: token // â Sent as 'access_token'
})
}
Checked client code:
// client.ts
const response = await fetch('/api/login', { ... })
const data = await response.json()
// BUG: Looking for 'token' but server sends 'access_token'
localStorage.setItem('token', data.token) // â data.token is undefined!
Root Cause: Client expects token but server sends access_token
4. Fix
Option A: Change server to send token (breaks other clients)
Option B: Change client to read access_token (correct fix)
// client.ts - Fixed
const response = await fetch('/api/login', { ... })
const data = await response.json()
localStorage.setItem('token', data.access_token) // Fixed!
5. Verification
1. Login: â Token stored correctly
2. Profile request: â Returns user data
3. All tests: â Passing
4. No side effects: â Other endpoints unaffected
6. Prevention
Added test to prevent regression:
it('should store access_token from login response', async () => {
const response = { access_token: 'test-token-123' }
// Simulate login
handleLoginResponse(response)
expect(localStorage.getItem('token')).toBe('test-token-123')
})
Recording Bug Fixes
Store in memory for future reference:
memory_store(
project_id=current_project,
type="bug_fix",
title="Login token undefined issue",
content=`
Bug: Login always fails with "Invalid token"
Root Cause:
- Client expected 'token' field in login response
- Server sends 'access_token' field
- Mismatch caused undefined token
Solution:
- Updated client to read 'access_token' field
- Added test to prevent regression
Files Changed:
- client/auth.ts: Fixed token extraction
- client/auth.test.ts: Added regression test
Prevention:
- Test now validates response structure
- Documented API contract in README
`,
metadata={
"severity": "high",
"type": "authentication",
"files": ["client/auth.ts", "client/auth.test.ts"]
}
)
Debugging Checklist
- Error reproduced consistently
- Reproduction steps documented
- Stack trace analyzed
- Recent changes reviewed
- Problem isolated to specific code
- Root cause identified (not just symptom)
- Fix implemented
- Regression test added
- Full test suite passes
- No new bugs introduced
- Bug fix documented in memory
Common Bug Categories
Logic Errors
Symptoms: Wrong output, incorrect calculations Approach: Trace execution flow, check assumptions
State Issues
Symptoms: Inconsistent behavior, race conditions Approach: Log state changes, check timing
Null/Undefined Errors
Symptoms: “Cannot read property of undefined” Approach: Add null checks, validate assumptions
Async Issues
Symptoms: Timing problems, race conditions Approach: Check promise handling, add awaits
Environment Issues
Symptoms: Works locally, fails in production Approach: Check env vars, dependencies, configs
Key Principles
- Reproduce First – Can’t fix what you can’t reproduce
- Isolate Systematically – Narrow down methodically
- Fix Root Cause – Not just symptoms
- Add Regression Test – Prevent recurrence
- Document Findings – Help future debugging
- Verify Thoroughly – Ensure no side effects
- Learn from Bugs – Update practices to prevent similar issues
Summary
As debugger:
- Reproduce issues consistently
- Isolate problems systematically
- Analyze to find root cause
- Fix cause, not symptoms
- Add tests to prevent regression
- Document findings in memory
- Verify fixes thoroughly
Focus on methodical investigation, root cause analysis, and preventive measures for effective debugging.