A systematic, scientific approach to finding and fixing bugs — replacing guesswork with method.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian Kernighan
Lock file changes, breaking API changes, peer dependency conflicts
Git Bisect Guide
When you know a bug was introduced between two commits, git bisect finds the exact breaking commit using binary search.
# 1. Start bisect
git bisect start
# 2. Mark the current (broken) commit as bad
git bisect bad
# 3. Mark a known good commit
git bisect good abc1234
# 4. Git checks out a middle commit — test it, then tell git:
git bisect good # if this commit works fine
git bisect bad # if this commit has the bug
# 5. Repeat until git identifies the first bad commit
# Output: "<commit-hash> is the first bad commit"
# 6. Examine the breaking commit
git show <commit-hash>
# 7. End the bisect session
git bisect reset
Automated Bisect
If you have a test script that exits 0 for good and non-zero for bad:
git bisect start
git bisect bad HEAD
git bisect good abc1234
git bisect run ./test-for-bug.sh
Git runs the script at each step automatically and reports the first bad commit.
Questions to Ask When Stuck
Use this checklist when you've been stuck for more than 15 minutes. Answer each question explicitly:
What changed recently? — new deploy, dependency update, config change, data migration?
Can I reproduce it? — reliably, intermittently, or not at all?
What are the exact error conditions? — specific input, user, environment, time of day?
What does the data look like? — inspect actual values, not what you assume they are
What do the logs say? — read them carefully, including timestamps and context
Does it happen in other environments? — local, staging, production, different OS/browser?
What is the expected behavior? — can I articulate exactly what should happen?
Have I seen this pattern before? — check the common bug categories table above
Am I looking at the right layer? — frontend vs backend, app vs infrastructure, code vs config?
What assumptions am I making? — list them explicitly, then verify each one
Time-Boxing
If you've spent more than 30 minutes without progress: step back and re-read the error from scratch, explain the problem aloud (rubber duck method), take a 10-minute break, try a completely different hypothesis, ask for help, or reduce scope by building the smallest reproduction from scratch.
Prevention
After fixing a bug, invest time to prevent its recurrence:
Action
How It Helps
Add a regression test
Ensures this exact bug cannot return undetected
Improve types
Catches null, undefined, and shape mismatches at compile time
Add runtime assertions
Fails fast with a clear message instead of silent corruption
Document the fix
Helps future developers understand the "why" behind the code
Review related code
The same mistake pattern may exist in similar locations
Update monitoring
Add alerts or dashboards so the symptom is caught earlier next time
Anti-Patterns
Behaviors that waste time and make bugs harder to find:
Anti-Pattern
Why It Fails
Do This Instead
Random changes
Introduces new bugs, obscures original cause
Follow the scientific method — one variable at a time
Fixing symptoms
The root cause remains and will resurface
Ask "why?" until you reach the actual defect
Debugging in production
Risk to users, limited tooling, high stress
Reproduce locally or in staging first
Not reproducing first
You cannot confirm a fix for a bug you cannot trigger
Invest the time to build a reliable reproduction
Ignoring error messages
The answer is often in the message you skipped
Read the full error, including stack trace and context
Assuming your code is correct
Confirmation bias hides obvious mistakes
Re-read your code as if someone else wrote it
Changing multiple things at once
You cannot tell which change fixed (or broke) it
Make one change, test, then move to the next
Debugging while fatigued
Tired debugging creates more bugs than it fixes
Take a break, come back with fresh eyes
NEVER Do
NEVER push a fix you cannot explain — if you don't know why it works, it doesn't work
NEVER debug without version control — always be able to revert to a known-good state
NEVER ignore a failing test — a skipped test is a hidden bug waiting to resurface
NEVER assume the bug is in someone else's code first — check your own code before blaming libraries or frameworks
NEVER debug while fatigued — tired debugging creates more bugs than it fixes
NEVER delete error handling to "simplify" — error handling is where bugs reveal themselves
NEVER skip the reproduction step — a fix without a reproduction is a guess, not a solution
NEVER make random changes hoping something works — follow the scientific method; one variable at a time
1---2name: debugging3description: Systematic debugging approaches — scientific method applied to code, structured techniques, common bug categories, git bisect, time-boxing, prevention strategies, and anti-patterns. Use when investigating bugs, diagnosing failures, or establishing debugging practices.4---56# Debugging Methodology78A systematic, scientific approach to finding and fixing bugs — replacing guesswork with method.910> "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian Kernighan111213## Installation1415### OpenClaw / Moltbot / Clawbot1617```bash18npx clawhub@latest install debugging19```202122---2324## Debugging Philosophy2526Debugging is not guessing. It is applied science.27281. **Observe** — gather evidence: error messages, logs, stack traces, screenshots, reproduction steps292. **Hypothesize** — form a specific, testable explanation for the behavior303. **Test** — design an experiment that confirms or disproves the hypothesis314. **Conclude** — accept or reject the hypothesis based on evidence, then iterate3233Every debugging session should follow this loop. If you catch yourself making random changes and re-running, stop — you've left the scientific method.3435---3637## Systematic Methods3839Choose the method that matches the situation:4041| Method | When to Use | How It Works |42|--------|-------------|-------------|43| **Binary search** | Large codebase, unknown origin | Bisect code or commits to narrow location by half each step |44| **Hypothesis testing** | Known symptoms, multiple possible causes | Form specific hypothesis, design targeted test, verify or refute |45| **Minimal reproduction** | Complex bugs, intermittent failures | Strip away code, config, and data until smallest case reproduces |46| **Trace analysis** | Flow-based bugs, wrong output | Follow data or execution path step by step from input to output |47| **Rubber duck** | Stuck, unclear thinking, no progress | Explain the problem aloud — forces clarity and often reveals the answer |48| **Divide and conquer** | Multi-component issues, integration bugs | Isolate each component, test independently, find which misbehaves |4950### Combining Methods5152Most real bugs require combining methods. A typical pattern:53541. Start with **trace analysis** to understand the flow552. Use **hypothesis testing** to narrow the cause563. Apply **binary search** (on code or commits) to pinpoint the location574. Build a **minimal reproduction** to confirm and share5859---6061## Debugging Workflow6263Follow these six steps in order. Do not skip ahead.6465### Step 1: Reproduce6667Can you make the bug happen reliably? Write down the exact steps.6869- What input triggers it?70- What environment (OS, browser, Node version)?71- Is it deterministic or intermittent?72- What is the expected behavior vs actual behavior?7374**If you cannot reproduce it, you cannot confirm you have fixed it.**7576### Step 2: Isolate7778Narrow the scope. Which component, file, function, or line?7980- Use binary search: comment out half the code, does it still fail?81- Use divide and conquer: test each component independently82- Check recent changes: `git log --oneline -20` and `git diff`8384### Step 3: Diagnose8586Understand the root cause, not just the symptom.8788- Ask "why?" repeatedly until you reach the actual defect89- Distinguish between the symptom (what you see) and the cause (why it happens)90- Verify your diagnosis by predicting what will happen if you change a specific thing9192### Step 4: Fix9394Make the smallest change that addresses the root cause.9596- Fix the cause, not the symptom97- Avoid side effects — don't "fix" by restructuring unrelated code98- If the fix is complex, break it into smaller, verifiable steps99100### Step 5: Verify101102Confirm the fix resolves the original reproduction case.103104- Run the exact reproduction steps from Step 1105- Check for regressions — did the fix break anything else?106- Test edge cases related to the bug107108### Step 6: Prevent109110Add safeguards so this class of bug cannot recur.111112- Write a regression test that reproduces the original bug113- Improve types, add assertions, or add validation114- Update monitoring or alerts if the bug was caught late115- Document the fix if the root cause was non-obvious116117---118119## Debugging Toolkit120121| Tool | Purpose | When to Reach for It |122|------|---------|---------------------|123| **Debugger** | Set breakpoints, step through execution, inspect state | Logic errors, unexpected control flow |124| **Logging** | Add strategic log statements at key points | Flow tracing, production issues, async bugs |125| **Profiler** | Measure CPU, memory, and timing | Performance regressions, slow endpoints |126| **Network inspector** | Inspect HTTP requests, responses, headers, timing | API integration bugs, auth failures, CORS |127| **Memory analyzer** | Heap snapshots, allocation tracking, leak detection | Memory leaks, growing memory usage |128129### Effective Logging130131- Include the **module and function name** as a prefix: `[OrderService.processPayment]`132- Log **inputs** on entry and **outputs/status** on exit133- Use **structured data** (objects), not string concatenation134- Remove debug logging before committing (or use a debug log level)135136---137138## Common Bug Categories139140Recognize the pattern to find the fix faster:141142| Category | Typical Symptoms | First Things to Check |143|----------|-----------------|----------------------|144| **Null reference** | "Cannot read property of undefined/null" | Input validation, optional chaining, API response shape |145| **Off-by-one** | Missing first/last item, extra iteration, boundary failure | Loop bounds, array indices, fence-post conditions |146| **Race condition** | Intermittent failures, order-dependent, works in debugger | Shared mutable state, missing locks/awaits, event ordering |147| **Memory leak** | Growing memory over time, eventual OOM or slowdown | Event listeners not removed, closures holding references, cache without eviction |148| **State management** | UI out of sync, stale data, phantom updates | Mutation vs immutability, missing re-renders, stale closures |149| **Encoding** | Garbled text, wrong characters, hash mismatches | UTF-8 vs Latin-1, URL encoding, base64 padding |150| **Timezone** | Times off by hours, wrong dates near midnight | UTC vs local, DST transitions, serialization format |151| **Async ordering** | Operations complete in unexpected order | Missing await, unhandled promise, callback timing |152| **Configuration** | Works locally, fails in staging/production | Environment variables, feature flags, config file differences |153| **Dependency version** | Broke after update, works with old version | Lock file changes, breaking API changes, peer dependency conflicts |154155---156157## Git Bisect Guide158159When you know a bug was introduced between two commits, `git bisect` finds the exact breaking commit using binary search.160161```bash162# 1. Start bisect163git bisect start164165# 2. Mark the current (broken) commit as bad166git bisect bad167168# 3. Mark a known good commit169git bisect good abc1234170171# 4. Git checks out a middle commit — test it, then tell git:172git bisect good # if this commit works fine173git bisect bad # if this commit has the bug174175# 5. Repeat until git identifies the first bad commit176# Output: "<commit-hash> is the first bad commit"177178# 6. Examine the breaking commit179git show <commit-hash>180181# 7. End the bisect session182git bisect reset183```184185### Automated Bisect186187If you have a test script that exits 0 for good and non-zero for bad:188189```bash190git bisect start191git bisect bad HEAD192git bisect good abc1234193git bisect run ./test-for-bug.sh194```195196Git runs the script at each step automatically and reports the first bad commit.197198---199200## Questions to Ask When Stuck201202Use this checklist when you've been stuck for more than 15 minutes. Answer each question explicitly:203204- [ ] **What changed recently?** — new deploy, dependency update, config change, data migration?205- [ ] **Can I reproduce it?** — reliably, intermittently, or not at all?206- [ ] **What are the exact error conditions?** — specific input, user, environment, time of day?207- [ ] **What does the data look like?** — inspect actual values, not what you assume they are208- [ ] **What do the logs say?** — read them carefully, including timestamps and context209- [ ] **Does it happen in other environments?** — local, staging, production, different OS/browser?210- [ ] **What is the expected behavior?** — can I articulate exactly what should happen?211- [ ] **Have I seen this pattern before?** — check the common bug categories table above212- [ ] **Am I looking at the right layer?** — frontend vs backend, app vs infrastructure, code vs config?213- [ ] **What assumptions am I making?** — list them explicitly, then verify each one214215---216217## Time-Boxing218219If you've spent more than 30 minutes without progress: step back and re-read the error from scratch, explain the problem aloud (rubber duck method), take a 10-minute break, try a completely different hypothesis, ask for help, or reduce scope by building the smallest reproduction from scratch.220221---222223## Prevention224225After fixing a bug, invest time to prevent its recurrence:226227| Action | How It Helps |228|--------|-------------|229| **Add a regression test** | Ensures this exact bug cannot return undetected |230| **Improve types** | Catches null, undefined, and shape mismatches at compile time |231| **Add runtime assertions** | Fails fast with a clear message instead of silent corruption |232| **Document the fix** | Helps future developers understand the "why" behind the code |233| **Review related code** | The same mistake pattern may exist in similar locations |234| **Update monitoring** | Add alerts or dashboards so the symptom is caught earlier next time |235236---237238## Anti-Patterns239240Behaviors that waste time and make bugs harder to find:241242| Anti-Pattern | Why It Fails | Do This Instead |243|--------------|-------------|-----------------|244| **Random changes** | Introduces new bugs, obscures original cause | Follow the scientific method — one variable at a time |245| **Fixing symptoms** | The root cause remains and will resurface | Ask "why?" until you reach the actual defect |246| **Debugging in production** | Risk to users, limited tooling, high stress | Reproduce locally or in staging first |247| **Not reproducing first** | You cannot confirm a fix for a bug you cannot trigger | Invest the time to build a reliable reproduction |248| **Ignoring error messages** | The answer is often in the message you skipped | Read the full error, including stack trace and context |249| **Assuming your code is correct** | Confirmation bias hides obvious mistakes | Re-read your code as if someone else wrote it |250| **Changing multiple things at once** | You cannot tell which change fixed (or broke) it | Make one change, test, then move to the next |251| **Debugging while fatigued** | Tired debugging creates more bugs than it fixes | Take a break, come back with fresh eyes |252253---254255## NEVER Do2562571. **NEVER push a fix you cannot explain** — if you don't know why it works, it doesn't work2582. **NEVER debug without version control** — always be able to revert to a known-good state2593. **NEVER ignore a failing test** — a skipped test is a hidden bug waiting to resurface2604. **NEVER assume the bug is in someone else's code first** — check your own code before blaming libraries or frameworks2615. **NEVER debug while fatigued** — tired debugging creates more bugs than it fixes2626. **NEVER delete error handling to "simplify"** — error handling is where bugs reveal themselves2637. **NEVER skip the reproduction step** — a fix without a reproduction is a guess, not a solution2648. **NEVER make random changes hoping something works** — follow the scientific method; one variable at a time
Run npx skillmds add wpank/debugging in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Systematic debugging approaches — scientific method applied to code, structured techniques, common bug categories, git bisect, time-boxing, prevention strategies, and anti-patterns. Use when investigating bugs, diagnosing failures, or establishing debugging practices. It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: docs only. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
wpank (@wpank) published this skill. Their other Agent Skills are listed on their SkillMD profile.