Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Comprehensive debugging specialist for errors, test failures, log analysis, and system problems. Use when encountering issues, analyzing error logs, investigating system anomalies, debugging production issues, analyzing stack traces, or identifying root causes. Combines general debugging workflows with error pattern detection and log analysis.
.claude/skills/aiskillstore-debugging/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | -19% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 71% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 310% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 54% | 0% |
| case-19 | ✓→✗ | ▼ Worse | 73% | 0% |
Collect all relevant context about the issue:
Error details:
Environment:
bash# Check recent changes git log --oneline -10 git diff HEAD~5 # Check dependency versions npm list --depth=0 # Node.js pip freeze # Python
Create a minimal, reproducible example:
python# Bad: Vague description "The function sometimes fails" # Good: Specific reproduction steps """ 1. Call process_data() with input: {"id": None} 2. Error occurs: TypeError at line 45 3. Expected: Return empty dict 4. Actual: Raises exception """ # Minimal reproduction def test_reproduce_bug(): result = process_data({"id": None}) # Fails here assert result == {}
Use binary search debugging to narrow down the issue:
Print/Log debugging:
pythondef problematic_function(data): print(f"[DEBUG] Input: {data}") # Entry point result = step_one(data) print(f"[DEBUG] After step_one: {result}") result = step_two(result) print(f"[DEBUG] After step_two: {result}") # Issue here? return step_three(result)
Divide and conquer:
python# Comment out half the code # If error persists: bug is in remaining half # If error gone: bug is in commented half # Repeat until isolated
Common bug patterns and solutions:
| Pattern | Symptom | Solution | |---------|---------|----------| | Off-by-one | Index out of bounds | Check loop bounds | | Null reference | NullPointerException | Add null checks | | Race condition | Intermittent failures | Add synchronization | | Memory leak | Gradual slowdown | Check resource cleanup | | Type mismatch | Unexpected behavior | Validate types |
Questions to ask:
Apply the fix with proper verification:
python# Before: Bug def get_user(user_id): return users[user_id] # KeyError if not found # After: Fix with proper handling def get_user(user_id): if user_id not in users: return None # Or raise custom exception return users[user_id]
Fix checklist:
Ensure the fix works and prevent regression:
python# Add test for the specific bug def test_bug_fix_issue_123(): """Regression test for issue #123: KeyError on missing user""" result = get_user("nonexistent_id") assert result is None # Should not raise # Add edge case tests @pytest.mark.parametrize("input,expected", [ (None, None), ("", None), ("valid_id", {"name": "User"}), ]) def test_get_user_edge_cases(input, expected): assert get_user(input) == expected
Error:
TypeError: cannot unpack non-iterable NoneType object
File "app.py", line 25, in process
name, email = get_user_info(user_id)Analysis:
python# Problem: get_user_info returns None when user not found def get_user_info(user_id): user = db.find_user(user_id) if user: return user.name, user.email # Missing: return None case! # Fix: Handle None case def get_user_info(user_id): user = db.find_user(user_id) if user: return user.name, user.email return None, None # Or raise UserNotFoundError
Symptom: Test passes locally, fails in CI intermittently
Analysis:
python# Problem: Shared state without synchronization class Counter: def __init__(self): self.value = 0 def increment(self): self.value += 1 # Not atomic! # Fix: Add thread safety import threading class Counter: def __init__(self): self.value = 0 self._lock = threading.Lock() def increment(self): with self._lock: self.value += 1
Tool: Use memory profiler
pythonfrom memory_profiler import profile @profile def process_large_data(): results = [] for item in large_dataset: results.append(transform(item)) # Memory grows return results # Fix: Use generator for large datasets def process_large_data(): for item in large_dataset: yield transform(item) # Memory efficient
| Language | Debugger | Profiler | |----------|----------|----------| | Python | pdb, ipdb | cProfile, memory_profiler | | JavaScript | Chrome DevTools | Performance tab | | Java | IntelliJ Debugger | JProfiler, VisualVM | | Go | Delve | pprof | | Rust | rust-gdb | cargo-flamegraph |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-06 | pass→pass | 16,722 | 14,785 | -12% | 1 | 1 | 0% | 2,871 | 4,220 | +47% | 0 | 0 | — |
case-01 | fail→fail | 20,375 | 13,813 | -32% | 1 | 1 | 0% | 3,946 | 4,573 | +16% | 0 | 0 | — |
case-02 | fail→fail | 34,502 | 20,868 | -40% | 1 | 1 | 0% | 6,910 | 5,624 | -19% | 0 | 0 | — |
case-03 | fail→pass | 39,019 | 22,494 | -42% | 1 | 1 | 0% | 6,866 | 5,588 | -19% | 0 | 0 | — |
case-04 | pass→pass | 14,054 | 12,695 | -10% | 1 | 1 | 0% | 2,522 | 4,071 | +61% | 0 | 0 | — |
case-05 | fail→pass | 13,844 | 14,438 | +4% | 1 | 1 | 0% | 2,513 | 4,308 | +71% | 0 | 0 | — |
case-07 | pass→pass | 14,869 | 14,025 | -6% | 1 | 1 | 0% | 2,653 | 4,066 | +53% | 0 | 0 | — |
case-08 | pass→pass | 17,081 | 20,166 | +18% | 1 | 1 | 0% | 2,800 | 5,155 | +84% | 0 | 0 | — |
case-09 | pass→pass | 14,385 | 12,512 | -13% | 1 | 1 | 0% | 2,571 | 3,749 | +46% | 0 | 0 | — |
case-10 | pass→pass | 7,722 | 5,496 | -29% | 1 | 1 | 0% | 1,437 | 2,698 | +88% | 0 | 0 | — |
case-15 | pass→pass | 11,870 | 9,311 | -22% | 1 | 1 | 0% | 2,340 | 3,352 | +43% | 0 | 0 | — |
case-11 | fail→fail | 12,095 | 10,158 | -16% | 1 | 1 | 0% | 2,147 | 3,402 | +58% | 0 | 0 | — |
case-12 | fail→pass | 3,068 | 3,659 | +19% | 1 | 1 | 0% | 569 | 2,335 | +310% | 0 | 0 | — |
case-13 | pass→pass | 3,177 | 18,026 | +467% | 1 | 1 | 0% | 604 | 2,240 | +271% | 0 | 0 | — |
case-14 | pass→pass | 8,109 | 6,027 | -26% | 1 | 1 | 0% | 1,594 | 2,776 | +74% | 0 | 0 | — |
case-21 | pass→pass | 21,962 | 13,273 | -40% | 1 | 1 | 0% | 3,933 | 4,190 | +7% | 0 | 0 | — |
case-16 | fail→pass | 13,988 | 11,301 | -19% | 1 | 1 | 0% | 2,306 | 3,547 | +54% | 0 | 0 | — |
case-17 | pass→pass | 10,748 | 10,561 | -2% | 1 | 1 | 0% | 1,879 | 3,462 | +84% | 0 | 0 | — |
case-18 | pass→pass | 7,181 | 4,728 | -34% | 1 | 1 | 0% | 1,204 | 2,375 | +97% | 0 | 0 | — |
case-19 | pass→fail | 12,971 | 11,992 | -8% | 1 | 1 | 0% | 2,119 | 3,658 | +73% | 0 | 0 | — |
case-20 | pass→pass | 42,407 | 27,571 | -35% | 1 | 1 | 0% | 8,230 | 6,985 | -15% | 0 | 0 | — |
case-22 | pass→pass | 15,036 | 15,740 | +5% | 1 | 1 | 0% | 3,396 | 4,574 | +35% | 0 | 0 | — |
case-23 | pass→pass | 10,514 | 12,304 | +17% | 1 | 1 | 0% | 2,420 | 4,533 | +87% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +13 percentage points is the difference between those two pass rates over the 23 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/21/2026 | +23% |
Other measured skills in the registry, with their headline benchmark lift.