| name | debugging |
| description | Systematic debugging methodology for finding and fixing bugs. Use when investigating issues, tracing errors, or fixing production problems. |
Debugging Skill
Methodical problem-solving approach for identifying and resolving bugs efficiently.
When to Use This Skill
- Investigating bug reports
- Tracing error origins
- Fixing production issues
- Understanding unexpected behavior
š Systematic Debugging Process
1. Reproduce the Issue
Before fixing, confirm you can reproduce:
**Reproduction Steps:**
1. Navigate to /dashboard
2. Click "Create New" button
3. Fill form with empty values
4. Click submit
5. **Expected**: Validation error shown
6. **Actual**: Page crashes with error
2. Isolate the Problem
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Is the bug in frontend or backend? ā
ā ā ā
ā Which component/function? ā
ā ā ā
ā What input triggers it? ā
ā ā ā
ā What's the expected vs actual? ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
3. Form Hypothesis
Based on symptoms, hypothesize potential causes:
- Recent code changes?
- Data-related issue?
- Race condition?
- Configuration problem?
- External dependency failure?
4. Test Hypothesis
Add targeted logging or use debugger to verify:
log.Printf("[DEBUG] Handler input: %+v", input)
log.Printf("[DEBUG] Database result: %+v, err: %v", result, err)
log.Printf("[DEBUG] Response: %+v", response)
5. Fix and Verify
- Make minimal fix for root cause
- Add regression test
- Verify fix doesn't break other functionality
š Common Bug Patterns
Null/Nil Reference
func (h *Handler) GetName(user *User) string {
return user.Name
}
func (h *Handler) GetName(user *User) string {
if user == nil {
return ""
}
return user.Name
}
Off-by-One Errors
for i := 0; i <= len(items); i++ {
process(items[i])
}
for i := 0; i < len(items); i++ {
process(items[i])
}
Race Conditions
var counter int
go func() { counter++ }()
go func() { counter++ }()
var counter int64
go func() { atomic.AddInt64(&counter, 1) }()
go func() { atomic.AddInt64(&counter, 1) }()
Memory Leaks
useEffect(() => {
window.addEventListener('resize', handleResize);
}, []);
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
Async/Await Issues
async function fetchData() {
const response = fetch('/api/data');
return response.json();
}
async function fetchData() {
const response = await fetch('/api/data');
return response.json();
}
š§ Debugging Tools
Go Debugging
Delve Debugger
go install github.com/go-delve/delve/cmd/dlv@latest
dlv debug ./cmd/main.go
(dlv) break main.go:42
(dlv) continue
(dlv) print variableName
(dlv) next
(dlv) step
Printf Debugging
import "github.com/davecgh/go-spew/spew"
spew.Dump(complexObject)
data, _ := json.MarshalIndent(obj, "", " ")
log.Printf("Object: %s", data)
Profiling
import _ "net/http/pprof"
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
Frontend Debugging
Browser DevTools
- Console: Error messages, console.log output
- Network: API requests/responses
- Sources: Breakpoints, step debugging
- React DevTools: Component state, props
React Query DevTools
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
function App() {
return (
<QueryClientProvider client={queryClient}>
<MyApp />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
Strategic Console Logging
console.group('Form Submission');
console.log('Form data:', formData);
console.log('Validation result:', validationResult);
console.groupEnd();
console.trace('How did we get here?');
console.time('API Call');
await fetchData();
console.timeEnd('API Call');
š¬ Root Cause Analysis
The 5 Whys Technique
**Problem**: User cannot login
1. Why? ā Login API returns 500 error
2. Why? ā Database query fails
3. Why? ā Connection pool exhausted
4. Why? ā Connections not being released
5. Why? ā Missing defer db.Close() in handler
**Root Cause**: Resource leak due to missing cleanup
**Fix**: Add proper connection release
Bisect to Find Culprit
git bisect start
git bisect bad HEAD
git bisect good v1.0.0
git bisect good
git bisect bad
git bisect reset
š Logging Best Practices
Structured Logging
import "go.uber.org/zap"
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("request processed",
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.Int("status", status),
zap.Duration("duration", time.Since(start)),
zap.String("request_id", requestID),
)
Log Levels
- ERROR: Failures requiring immediate attention
- WARN: Unexpected but recoverable situations
- INFO: Important business events
- DEBUG: Detailed diagnostic information
What to Log
ā
Do Log:
- Request/response metadata (not sensitive data)
- Error details with context
- Performance metrics
- Security events (login attempts, permission denials)
ā Don't Log:
- Passwords, API keys, tokens
- Personal identifiable information (PII)
- Credit card numbers
- Health information
š References