| name | debugging |
| description | Systematic debugging methodology for isolating and fixing bugs efficiently. Use when encountering errors, unexpected behavior, test failures, or investigating issues. Triggers on debug, bug, error, fix, issue, troubleshoot, not working, broken, investigate. |
Systematic Debugging
A structured approach to isolating and resolving bugs efficiently, based on proven debugging methodologies.
When to Use This Skill
- Encountering runtime errors
- Test failures
- Unexpected behavior
- Performance issues
- Investigating reported bugs
- Understanding unfamiliar code
Debugging Methodology
Phase 1: Understand the Problem
Before touching code, gather information:
-
Reproduce the Issue
- Get exact reproduction steps
- Identify what triggers the bug
- Note when it started (recent changes?)
-
Define Expected vs Actual
Expected: User clicks "Start Session" → Session starts, UI shows running state
Actual: User clicks "Start Session" → Nothing happens, no error in console
-
Gather Context
- Check error messages and stack traces
- Review recent git commits
- Check if it worked before (and what changed)
Phase 2: Isolate the Problem
Narrow down the scope systematically:
async function startSession(outcomeId: string) {
console.log('[DEBUG] 1. Starting session for:', outcomeId);
const outcome = await getOutcome(outcomeId);
console.log('[DEBUG] 2. Got outcome:', outcome?.id);
if (!outcome) {
console.log('[DEBUG] 2a. Outcome not found, returning early');
return;
}
const session = await createSession(outcome);
console.log('[DEBUG] 3. Created session:', session?.id);
await notifyUI(session);
console.log('[DEBUG] 4. UI notified');
}
Isolation techniques:
- Add strategic logging at entry/exit points
- Check if issue is in frontend, backend, or IPC
- Verify data at each boundary
- Test with minimal reproduction case
Phase 3: Form Hypothesis
Based on evidence, form specific hypotheses:
## Hypothesis Log
### H1: IPC handler not registered
- Evidence: Console shows "invoke" called but no response
- Test: Add logging to main process IPC handler
- Result: ❌ Handler is registered
### H2: Promise not awaited
- Evidence: Function returns before async work completes
- Test: Add await to database call
- Result: ✅ Missing await found!
Phase 4: Implement Fix
Make targeted, minimal changes:
async function handleAction(step: AgentStep) {
this.executeToolCall(step.toolCall);
this.updateUI();
}
async function handleAction(step: AgentStep) {
await this.executeToolCall(step.toolCall);
this.updateUI();
}
Phase 5: Verify & Prevent
-
Verify the fix:
- Run original reproduction steps
- Check edge cases
- Run test suite
-
Prevent regression:
test('should wait for tool execution before updating UI', async () => {
const step = createMockStep({ type: 'tool_call' });
const handler = new ActionHandler();
let executionCompleted = false;
handler.executeToolCall = async () => {
await delay(100);
executionCompleted = true;
};
await handler.handleAction(step);
expect(executionCompleted).toBe(true);
});
Common Bug Patterns
Async/Await Issues
async function saveAndNotify(data: Data) {
db.insert(data);
notify('saved');
}
items.forEach(async (item) => {
await processItem(item);
});
for (const item of items) {
await processItem(item);
}
await Promise.all(items.map(item => processItem(item)));
State Management Bugs
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCount(count + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
}
useEffect(() => {
const interval = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
Race Conditions
async function loadUserData(userId: string) {
const user = await fetchUser(userId);
setUser(user);
}
function useUserData(userId: string) {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
const controller = new AbortController();
fetchUser(userId, { signal: controller.signal })
.then(setUser)
.catch(e => {
if (e.name !== 'AbortError') throw e;
});
return () => controller.abort();
}, [userId]);
return user;
}
Type Coercion Bugs
if (count == '0') { }
if (items == null) { }
if (count === 0) { }
if (items === null) { }
if (items === undefined) { }
if (items == null) { }
Debugging Tools
Console Methods
console.group('Session Start');
console.log('Outcome:', outcomeId);
console.log('User:', userId);
console.groupEnd();
console.table(tasks.map(t => ({ id: t.id, status: t.status })));
console.time('fetchData');
await fetchData();
console.timeEnd('fetchData');
console.assert(items.length > 0, 'Items should not be empty');
console.trace('How did we get here?');
Electron DevTools
mainWindow.webContents.openDevTools();
ipcMain.on('*', (event, channel, ...args) => {
console.log('[IPC]', channel, args);
});
const used = process.memoryUsage();
console.log(`Memory: ${Math.round(used.heapUsed / 1024 / 1024)}MB`);
Node.js Debugging
node --inspect src/main/index.ts
node --inspect-brk src/main/index.ts
{
"type": "node",
"request": "launch",
"name": "Debug Main",
"runtimeExecutable": "bun",
"args": ["run", "dev:main"],
"console": "integratedTerminal"
}
Debug Log Template
Use this template when investigating bugs:
# Bug Investigation: [Brief Description]
## Problem Statement
- Expected: [What should happen]
- Actual: [What happens]
- Reproduction: [Steps to reproduce]
## Investigation Log
### [Timestamp] Initial Analysis
- [Observations]
- [Initial hypotheses]
### [Timestamp] Hypothesis 1: [Description]
- Test: [What I tried]
- Result: [What happened]
- Conclusion: [Confirmed/Ruled out]
### [Timestamp] Root Cause Found
- [Description of root cause]
- [Why it causes the bug]
## Fix
- [Description of fix]
- [Files changed]
## Prevention
- [Test added]
- [Documentation updated]
Troubleshooting Quick Reference
| Symptom | Common Causes | Investigation |
|---|
| Nothing happens on click | Event handler not attached, error swallowed | Check console, add click logging |
| State not updating | Wrong dependency array, stale closure | Check useEffect deps, use functional update |
| Data not saving | Missing await, transaction rolled back | Check async flow, database logs |
| UI flickers | Unnecessary re-renders, layout thrashing | React DevTools Profiler |
| Memory grows | Event listener leak, closure holding reference | Heap snapshot, check cleanup |
| IPC timeout | Handler throwing, wrong channel name | Log both sides, verify channel |