bug-hunter

📁 xkayo32/agent-memory-orchestrator 📅 2 days ago
3
总安装量
3
周安装量
#57045
全站排名
安装命令
npx skills add https://github.com/xkayo32/agent-memory-orchestrator --skill bug-hunter

Agent 安装分布

opencode 3
github-copilot 3
codex 3
kimi-cli 3
gemini-cli 3
amp 3

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:

  1. Implement fix
  2. Verify original issue resolved
  3. Run full test suite
  4. Check for side effects
  5. 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

  1. Reproduce First – Can’t fix what you can’t reproduce
  2. Isolate Systematically – Narrow down methodically
  3. Fix Root Cause – Not just symptoms
  4. Add Regression Test – Prevent recurrence
  5. Document Findings – Help future debugging
  6. Verify Thoroughly – Ensure no side effects
  7. 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.