debugging-methodology
Scientific debugging methodology including hypothesis-driven debugging, bug reproduction, binary search debugging, stack trace analysis, logging strategies, and root cause analysis. Use when debugging errors, analyzing stack traces, investigating bugs, or troubleshooting performance issues.
What this skill does
# Debugging Methodology
This skill provides comprehensive guidance for systematically debugging issues using scientific methods and proven techniques.
## Scientific Debugging Method
### The Scientific Approach
**1. Observe**: Gather information about the bug
**2. Hypothesize**: Form theories about the cause
**3. Test**: Design experiments to test hypotheses
**4. Analyze**: Evaluate results
**5. Conclude**: Fix the bug or refine hypothesis
### Example: Debugging a Login Issue
```typescript
// Bug: Users cannot log in
// 1. OBSERVE
// - Error message: "Invalid credentials"
// - Happens for all users
// - Started after last deployment
// - Logs show: "bcrypt compare failed"
// 2. HYPOTHESIZE
// Hypothesis 1: Password comparison logic is broken
// Hypothesis 2: Database passwords corrupted
// Hypothesis 3: Bcrypt library updated with breaking change
// 3. TEST
// Test 1: Check if bcrypt library version changed
const packageLock = await fs.readFile('package-lock.json');
// Result: bcrypt upgraded from 5.0.0 to 6.0.0
// Test 2: Check bcrypt changelog
// Result: v6.0.0 changed default salt rounds
// Test 3: Verify password hashing
const testPassword = 'password123';
const oldHash = '$2b$10$...'; // From database
const newHash = await bcrypt.hash(testPassword, 10);
console.log(await bcrypt.compare(testPassword, oldHash)); // false
console.log(await bcrypt.compare(testPassword, newHash)); // true
// 4. ANALYZE
// Old hashes use $2b$ format, new version uses $2a$ format
// Incompatible hash formats
// 5. CONCLUDE
// Rollback bcrypt to 5.x or migrate all password hashes
```
## Reproducing Bugs Consistently
### Creating Minimal Reproduction
```typescript
// Original bug report: "App crashes when clicking submit"
// Step 1: Remove unrelated code
// ❌ BAD - Too much noise
function handleSubmit() {
validateForm();
checkPermissions();
logAnalytics();
sendToServer();
updateUI();
showNotification();
// Which one causes the crash?
}
// ✅ GOOD - Minimal reproduction
function handleSubmit() {
// Removed: validateForm, checkPermissions, logAnalytics, updateUI, showNotification
// Bug still occurs with just:
sendToServer();
// Root cause: sendToServer crashes with undefined data
}
```
### Reproducing Race Conditions
```typescript
// Bug: Intermittent "Cannot read property of undefined"
// Make race condition reproducible with delays
async function fetchUserData() {
const user = await fetchUser();
// Add artificial delay to make race condition consistent
await new Promise(resolve => setTimeout(resolve, 100));
return user.profile; // Sometimes undefined
}
// Once reproducible, investigate:
// - Are multiple requests racing?
// - Is data being cleared too early?
// - Are promises resolving out of order?
```
### Creating Test Cases
```typescript
// Once bug is reproducible, create failing test
describe('Login', () => {
test('should authenticate user with valid credentials', async () => {
const user = await db.user.create({
email: '[email protected]',
password: await bcrypt.hash('password123', 10),
});
const result = await login('[email protected]', 'password123');
expect(result.success).toBe(true);
expect(result.user.email).toBe('[email protected]');
});
});
```
## Binary Search Debugging
### Finding the Breaking Commit
```bash
# Use git bisect to find the commit that introduced the bug
# Start bisect
git bisect start
# Mark current commit as bad (has the bug)
git bisect bad
# Mark a known good commit (before bug appeared)
git bisect good v1.2.0
# Git will checkout a commit in the middle
# Test if bug exists, then mark:
git bisect bad # Bug exists in this commit
# or
git bisect good # Bug doesn't exist in this commit
# Repeat until git identifies the breaking commit
# Git will output: "abc123 is the first bad commit"
# End bisect session
git bisect reset
```
### Automated Bisect
```bash
# Create test script that exits 0 (pass) or 1 (fail)
# test.sh
#!/bin/bash
npm test 2>&1 | grep -q "Login test failed"
if [ $? -eq 0 ]; then
exit 1 # Bug found
else
exit 0 # Bug not found
fi
# Run automated bisect
git bisect start HEAD v1.2.0
git bisect run ./test.sh
# Git will automatically find the breaking commit
```
### Binary Search in Code
```typescript
// Bug: Function returns wrong result for large arrays
function processArray(arr: number[]): number {
// 100 lines of code
// Which line causes the bug?
}
// Binary search approach:
// 1. Comment out second half
function processArray(arr: number[]): number {
// Lines 1-50
// Lines 51-100 (commented out)
}
// If bug disappears: Bug is in lines 51-100
// If bug persists: Bug is in lines 1-50
// 2. Repeat on the problematic half
// Continue until you isolate the buggy line
```
## Stack Trace Analysis
### Reading Stack Traces
```
Error: Cannot read property 'name' of undefined
at getUserName (/app/src/user.ts:42:20)
at formatUserProfile (/app/src/profile.ts:15:25)
at handleRequest (/app/src/api.ts:89:30)
at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
```
**Analysis**:
1. **Error type**: TypeError - trying to access property on undefined
2. **Error message**: "Cannot read property 'name' of undefined"
3. **Origin**: `getUserName` function at line 42
4. **Call chain**: api.ts → profile.ts → user.ts
5. **Root cause location**: user.ts:42
### Investigating the Stack Trace
```typescript
// user.ts:42
function getUserName(userId: string): string {
const user = cache.get(userId);
return user.name; // ← Line 42: user is undefined
}
// Why is user undefined?
// 1. Check cache.get implementation
// 2. Check if userId is valid
// 3. Check if user exists in cache
// Add defensive check:
function getUserName(userId: string): string {
const user = cache.get(userId);
if (!user) {
throw new Error(`User not found in cache: ${userId}`);
}
return user.name;
}
```
### Source Maps for Production
```javascript
// Enable source maps in production
// webpack.config.js
module.exports = {
devtool: 'source-map',
// This generates .map files for production debugging
};
// View original TypeScript code in production errors
// Instead of:
// at r (/app/bundle.js:1:23456)
// You see:
// at getUserName (/app/src/user.ts:42:20)
```
## Logging Strategies
### Strategic Log Placement
```typescript
// ✅ GOOD - Log at key decision points
async function processOrder(order: Order) {
logger.info('Processing order', { orderId: order.id, items: order.items.length });
try {
// Log before critical operations
logger.debug('Validating order', { orderId: order.id });
await validateOrder(order);
logger.debug('Processing payment', { orderId: order.id, amount: order.total });
const payment = await processPayment(order);
logger.info('Order processed successfully', {
orderId: order.id,
paymentId: payment.id,
duration: Date.now() - startTime,
});
return payment;
} catch (error) {
// Log errors with context
logger.error('Order processing failed', {
orderId: order.id,
error: error.message,
stack: error.stack,
});
throw error;
}
}
```
### Structured Logging
```typescript
import winston from 'winston';
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
defaultMeta: {
service: 'order-service',
version: process.env.APP_VERSION,
},
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});
// Output:
// {
// "timestamp": "2025-10-16T10:30:00.000Z",
// "level": "error",
// "message": "Order processing failed",
// "orderId": "order_123",
// "error": "Payment declined",
// "service": "order-serviRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.