All skills
Skillintermediate

Runtime Bug Audit

Find runtime bugs and error handling issues. **NOT for security vulnerabilities** (use security-auditor for that).

Claude Code Knowledge Pack7/10/2026

Overview

Runtime Bug Audit

Find runtime bugs and error handling issues. NOT for security vulnerabilities (use security-auditor for that).

Output to .claude/audits/AUDIT_BUGS.md.

Status Block (Required)

Every output MUST start with:

---
agent: bug-auditor
status: COMPLETE | PARTIAL | SKIPPED | ERROR
timestamp: [ISO timestamp]
duration: [seconds]
findings: [count]
errors: []
skipped_checks: []
---

Scope (NON-OVERLAPPING)

bug-auditor checks:

  • Runtime bugs (null refs, type errors)
  • Error handling gaps (empty catch, unhandled rejections)
  • Race conditions (TOCTOU, concurrent state)
  • Resource leaks (memory, event listeners, timers)
  • State management bugs
  • Async/await issues

Does NOT check (use security-auditor instead):

  • SQL injection
  • XSS
  • Command injection
  • Auth/session issues
  • Hardcoded secrets
  • CSRF

Check

Error Handling

  • Empty catch blocks
  • Unhandled promise rejections
  • Missing error boundaries (React)
  • Try-catch without logging
  • Swallowed errors
  • Generic catch-all handlers

Null/Undefined Safety

  • Optional chaining gaps
  • Missing null checks before access
  • Undefined function returns
  • Array access without bounds check
  • Object property access without existence check

Race Conditions

  • TOCTOU (Time-of-check-to-time-of-use)
  • Concurrent state mutations
  • Non-atomic operations on shared state
  • Missing locks/semaphores
  • Stale closure values

Resource Leaks

  • Event listeners not removed
  • Subscriptions not unsubscribed
  • Timers not cleared (setInterval, setTimeout)
  • Open connections not closed
  • File handles not closed
  • AbortController not used for fetch

Async Issues

  • Missing await
  • Floating promises
  • Async in loops without Promise.all
  • Sequential awaits that could be parallel
  • Promise.all without error handling

State Management

  • Direct state mutation (React)
  • Stale state in callbacks
  • Missing dependency array items (useEffect)
  • Infinite useEffect loops
  • State updates after unmount

Grep Patterns

# Empty catch blocks
grep -rn "catch\\s*(\\s*[a-z]*\\s*)\\s*{\\s*}" src --include="*.ts" --include="*.tsx" | head -10

# Catch blocks that swallow errors
grep -rn "catch.*{" -A 2 src --include="*.ts" --include="*.tsx" | grep -B 1 "^\\s*}" | head -20

# Missing await (async function without await usage)
grep -rn "async.*=>" src --include="*.ts" --include="*.tsx" | head -10

# Event listeners without cleanup
grep -rn "addEventListener" src --include="*.ts" --include="*.tsx" | head -10

# setInterval without clearInterval
grep -rn "setInterval" src --include="*.ts" --include="*.tsx" | head -10

# Direct array index access (potential undefined)
grep -rn "\\[0\\]\\|\\[i\\]\\|\\[index\\]" src --include="*.ts" --include="*.tsx" | grep -v "length" | head -10

# useEffect without cleanup return
grep -rn "useEffect\\s*(" -A 10 src --include="*.tsx" | head -30

# State updates without functional form (stale state risk)
grep -rn "setState.*state\\." src --include="*.tsx" | head -10

# Floating promises (promise not awaited or .catch()ed)
grep -rn "\\.then\\s*(" src --include="*.ts" | grep -v "\\.catch\\|await\\|return" | head -10

# Missing dependency array
grep -rn "useEffect\\|useCallback\\|useMemo" -A 3 src --include="*.tsx" | grep -v "\\[\\]" | head -20

Output

# Runtime Bug Audit

---
agent: bug-auditor
status: [COMPLETE|PARTIAL|SKIPPED]
timestamp: [ISO timestamp]
duration: [X seconds]
findings: [X]
errors: [list any errors]
skipped_checks: [list checks that couldn't run]
---

## Summary
| Category | Count |
|----------|-------|
| Error Handling | X |
| Null Safety | X |
| Race Conditions | X |
| Resource Leaks | X |
| Async Issues | X |
| State Bugs | X |

## Critical

### BUG-001: Empty Catch Block Swallows Errors
**File:** `src/lib/api.ts:45`
**Issue:** Error caught but not logged or handled
```typescript
try {
  await fetchData();
} catch (e) {
  // Error silently swallowed
}

Impact: Bugs go undetected, silent failures Fix:

try {
  await fetchData();
} catch (e) {
  console.error('Failed to fetch data:', e);
  throw e; // or handle gracefully
}

BUG-002: Missing await on async function

File: src/hooks/useAuth.ts:23 Issue: Async function called without await

validateToken(token); // Missing await!

Impact: Race condition, validation may not complete before use Fix:

await validateToken(token);

High

BUG-003: Event listener not removed

File: src/components/ScrollTracker.tsx:15 Issue: addEventListener without removeEventListener

useEffect(() => {
  window.addEventListener('scroll', handleScroll);
  // Missing cleanup!
}, []);

Impact: Memory leak, duplicate handlers Fix:

useEffect(() => {
  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, []);

BUG-004: setInterval without cleanup

File: src/components/Timer.tsx:8 Issue: setInterval not cleared on unmount

useEffect(() => {
  setInterval(() => setCount(c => c + 1), 1000);
}, []);

Impact: Timer continues after unmount, memory leak Fix:

useEffect(() => {
  const id = setInterval(() => setCount(c => c + 1), 1000);
  return () => clearInterval(id);
}, []);

BUG-005: Stale closure in callback

File: src/hooks/useData.ts:30 Issue: Using stale state value in callback

const onClick = () => {
  setCount(count + 1); // count is stale!
};

Impact: State updates lost, incorrect values Fix:

const onClick = () => {
  setCount(c => c + 1); // Use functional form
};

Medium

BUG-006: Array access without bounds check

File: src/utils/helpers.ts:12 Issue: Accessing array[0] without checking length

const first = items[0]; // May be undefined

Fix:

const first = items?.[0];
// or
const first = items.length > 0 ? items[0] : null;

BUG-007: Missing error boundary

File: src/app/layout.tsx Issue: No ErrorBoundary wrapping page content Impact: Uncaught errors crash entire app Fix: Add React ErrorBoundary component

BUG-008: Floating promise (not awaited)

File: src/services/analytics.ts:25 Issue: Promise not awaited or caught

trackEvent('page_view'); // Fire and forget, no error handling

Fix:

trackEvent('page_view').catch(console.error);

Low

BUG-009: Console.log in production code

File: Multiple files Issue: Debug statements left in code Fix: Remove or use proper logging library

Checklist

Error Handling

  • All catch blocks log or handle errors
  • Error boundaries wrap React components
  • Async functions have try-catch
  • Promise rejections are handled

Resource Management

  • Event listeners have cleanup
  • Timers are cleared
  • Subscriptions are unsubscribed
  • AbortController used for fetch

State Safety

  • Functional setState for dependent updates
  • useEffect has proper dependencies
  • No state updates after unmount
  • No direct state mutation

## Execution Logging

After completing, append to `.claude/audits/EXECUTION_LOG.md`:

| [timestamp] | bug-auditor | [status] | [duration] | [findings] | [errors] |


## Output Verification

Before completing:
1. Verify `.claude/audits/AUDIT_BUGS.md` was created
2. Verify file has content beyond headers
3. If no issues found, write "No runtime bugs detected" (not empty file)

Focus on runtime bugs. **Do NOT duplicate security checks** - those belong in security-auditor.