Systematic Debugging
Systematic Debugging
The Fundamental Rule
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST.
Quick patches create technical debt. Symptoms mask deeper issues. Every fix must address the actual root cause.
The Four Phases
Phase 1: Root Cause Investigation
Before touching code, gather evidence:
-
Read the error carefully
Error: Cannot read properties of undefined (reading 'map') at ProductList (src/components/ProductList.tsx:15:24) at renderWithHooks (node_modules/react-dom/...)- What exactly failed?
- Where in the stack trace?
- What data was involved?
-
Reproduce consistently
# Document exact reproduction steps 1. Navigate to /products 2. Click "Filter by category" 3. Select "Electronics" 4. Error appears -
Check recent changes
git log --oneline -10 git diff HEAD~3 -- src/components/ProductList.tsx -
Add instrumentation at boundaries
// Before the failing line console.log('products:', JSON.stringify(products, null, 2)); console.log('type:', typeof products); console.log('isArray:', Array.isArray(products));
Phase 2: Pattern Analysis
Find working examples and compare:
// Working component
const WorkingList = ({ items }) => {
if (!items || items.length === 0) return <Empty />;
return items.map(item => <Item key={item.id} {...item} />);
};
// Broken component - what's different?
const BrokenList = ({ items }) => {
return items.map(item => <Item key={item.id} {...item} />);
// Missing: null check before .map()
};
Key questions:
- What does working code do that broken code doesn't?
- What assumptions does broken code make?
- Where do the data flows diverge?
Phase 3: Hypothesis and Testing
Apply the scientific method:
-
Form specific hypothesis
"The error occurs because
productsis undefined on initial render before the API response arrives." -
Test with minimal change
// Test hypothesis: add early return if (!products) return <Loading />; -
One variable at a time
- Don't bundle multiple fixes
- Change one thing, test, observe
- Document what you learned
Phase 4: Implementation
-
Write failing test FIRST
it('should handle undefined products gracefully', () => { render(<ProductList products={undefined} />); expect(screen.getByText('Loading...')).toBeInTheDocument(); }); -
Implement root cause fix
// Fix at the source, not symptoms const ProductList = ({ products }: Props) => { if (!products) return <Loading />; if (products.length === 0) return <Empty />; return ( <ul> {products.map(product => ( <ProductItem key={product.id} product={product} /> ))} </ul> ); }; -
Verify without bundling
- Only the fix, nothing else
- Run full test suite
- Confirm original issue resolved
Red Flags - Stop and Reassess
| Warning Sign | Action |
|---|---|
| Proposing fix before understanding | Go back to Phase 1 |
| Multiple simultaneous changes | Isolate to one change |
| Third fix attempt failing | Question the architecture |
| "It works but I don't know why" | Keep investigating |
The Three-Fix Rule
If you've tried 3 fixes without success:
- STOP - More fixes won't help
- Step back - Is the architecture flawed?
- Document - What did each attempt reveal?
- Reconsider - Is this the right approach at all?
Debugging Toolkit
Console Methods
console.log() // Basic output
console.table() // Tabular data
console.trace() // Stack trace
console.time() // Performance timing
console.group() // Grouped logs
React DevTools
- Component props inspection
- State timeline
- Profiler for performance
Network Tab
- Request/response payloads
- Timing analysis
- Failed requests
Breakpoints
// Conditional breakpoint
debugger; // Only when condition met
// Logpoint (VS Code)
// Right-click line → Add Logpoint
FrankX-Specific Patterns
Next.js Server Components
// Common issue: using client hooks in server components
// Phase 1: Check if component has 'use client'
// Phase 2: Compare with working client components
// Phase 3: Add 'use client' or restructure
API Route Debugging
// Add request logging
export async function POST(request: Request) {
console.log('=== API DEBUG ===');
const body = await request.json();
console.log('Body:', JSON.stringify(body, null, 2));
console.log('Headers:', Object.fromEntries(request.headers));
// ... rest of handler
}
Hydration Mismatches
// Phase 1: Check for Date.now(), Math.random(), or browser APIs
// Phase 2: Find server vs client render differences
// Phase 3: Use useEffect for client-only code
// Phase 4: Verify with 'suppressHydrationWarning' as last resort
When to Use This Skill
- Any bug that isn't immediately obvious
- Bugs that "shouldn't be possible"
- Issues that keep coming back
- Problems others have already attempted to fix
Related Skills
test-driven-development- Write test for bug firstwebapp-testing- E2E debugging with Playwrightverification-before-completion- Ensure fix actually works
More from frankxai/ai-and-web3
cacos
Claude Agentic Creator OS - Native Claude Code implementation
1test-driven development
Enforce RED-GREEN-REFACTOR cycle for reliable, maintainable code
1spartan warrior
Embody the unbreakable Spartan ethos of discipline, courage, and relentless excellence through laconic wisdom and warrior mentality forged in hardship
1framer expert
Expert in Framer design and development - from interactive prototypes to production sites with Framer Motion, CMS integration, and the Framer MCP server
1skill creator
Meta-skill for creating high-quality Claude Code skills
1golden path
The journey Life Book - walk your path to the Golden Age through 7 Waypoints
1