| name | root-cause-tracing |
| description | Use when errors occur deep in execution and you need to trace back to find the original trigger - systematically traces bugs backward through call stack to identify source of invalid data |
Root Cause Tracing
Overview
Bugs often manifest deep in the call stack. Your instinct is to fix where the error appears, but that's treating a symptom.
Core principle: Trace backward through the call chain until you find the original trigger, then fix at the source.
When to Use
- Error happens deep in execution (not at entry point)
- Stack trace shows long call chain
- Unclear where invalid data originated
- Need to find which code triggers the problem
The Tracing Process
1. Observe the Symptom
Error: database query failed with null user_id
2. Find Immediate Cause
What code directly causes this?
await db.query('SELECT * FROM orders WHERE user_id = ?', [userId]);
3. Ask: What Called This?
OrderService.getOrders(userId)
→ called by OrderController.list()
→ called by router.get('/orders')
→ called by auth middleware
4. Keep Tracing Up
What value was passed?
userId = null- Where did null come from?
- Auth middleware didn't set user on request
5. Find Original Trigger
Where did the problem originate?
// Auth middleware bug: didn't handle expired tokens
if (token.expired) {
// Missing: return error response
// Falls through with req.user = undefined
}
Adding Stack Traces
When you can't trace manually, add instrumentation:
async function getOrders(userId: string) {
const stack = new Error().stack;
console.error('DEBUG getOrders:', {
userId,
typeOfUserId: typeof userId,
stack,
});
// ... rest of function
}
Run and capture:
npm test 2>&1 | grep 'DEBUG getOrders'
Real Example
Symptom: .git created in source directory during tests
Trace chain:
git initruns inprocess.cwd()← empty cwd parameter- WorktreeManager called with empty projectDir
- Session.create() passed empty string
- Test accessed
context.tempDirbefore beforeEach - setupTest() returns
{ tempDir: '' }initially
Root cause: Top-level variable initialization accessing empty value
Fix: Made tempDir a getter that throws if accessed too early
Key Principle
Found immediate cause
↓
Can trace one level up? → YES → Trace backwards
↓ ↓
NO Is this the source?
↓ ↓
NEVER fix just YES → Fix at source
the symptom ↓
Add validation at each layer
↓
Bug impossible
NEVER fix just where the error appears. Trace back to find the original trigger.
Stack Trace Tips
- In tests: Use
console.error()not logger - logger may be suppressed - Before operation: Log before the dangerous operation, not after it fails
- Include context: Directory, cwd, environment variables
- Capture stack:
new Error().stackshows complete call chain
Integration
Used by:
- systematic-debugging - Phase 1, Step 5 calls this skill
Pairs with:
- defense-in-depth - After finding root cause, add validation at each layer