bug-root-cause-finder

Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.

dykyi-roman/awesome-claude-code18 installsMITSynced Aug 22

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: bug-root-cause-finder
description: Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.
license: MIT
---

# Bug Root Cause Finder

Systematic methods for finding the true source of bugs, not just symptoms.

## Core Principle: Symptom ≠ Cause

The location where an error manifests is rarely where the bug originates.

```
Error Location:     OrderController::show() - NullPointerException
Symptom Location:   OrderRepository::find() - returns null
Root Cause:         OrderCreatedHandler - failed to persist order
True Root Cause:    RabbitMQ message lost due to missing ACK
```

## Method 1: 5 Whys Technique

Ask "why" repeatedly until you reach the root cause.

### Example Analysis

**Bug:** "Customer sees wrong order total"

1. **Why?** → The total displayed is $0
2. **Why?** → `Order::getTotal()` returns 0
3. **Why?** → `OrderItem` collection is empty
4. **Why?** → Items weren't loaded from database
5. **Why?** → Lazy loading failed due to closed EntityManager

**Root Cause:** EntityManager closed before accessing lazy-loaded collection

**Fix:** Eager load items in repository query, not lazy load

### 5 Whys Template

```markdown
## 5 Whys Analysis

**Bug Description:** [What user sees]

1. Why does [symptom] occur?
   → [First-level cause]

2. Why does [first-level cause] happen?
   → [Second-level cause]

3. Why does [second-level cause] happen?
   → [Third-level cause]

4. Why does [third-level cause] happen?
   → [Fourth-level cause]

5. Why does [fourth-level cause] happen?
   → [ROOT CAUSE]

**Fix Location:** [File:line where fix should be applied]
**Fix Type:** [Category: logic/null/boundary/race/resource/exception/type/sql/infinite]
```

## Method 2: Fault Tree Analysis

Build a tree of all possible causes for a failure.

### Fault Tree Structure

```
[FAILURE: Order total is $0]
        │
        ├── [OR] Order has no items
        │       ├── [AND] Items not added during creation
        │       │       ├── Cart was empty
        │       │       └── Cart-to-Order mapping failed
        │       │
        │       └── [AND] Items were deleted
        │               ├── Cascade delete triggered
        │               └── Manual deletion bug
        │
        └── [OR] Items exist but total calculation wrong
                ├── Price is 0
                │       ├── Product price not set
                │       └── Currency conversion failed
                │
                └── Quantity is 0
                        ├── Validation missing
                        └── Type coercion (string "0")
```

### Fault Tree Investigation Order

1. Start with most likely branches (based on code review)
2. Add logging/debugging to verify each branch
3. Eliminate branches systematically
4. Focus on remaining possibilities

## Method 3: Git Bisect

Find the exact commit that introduced a bug.

### Git Bisect Steps

```bash
# 1. Start bisect
git bisect start

# 2. Mark current (broken) as bad
git bisect bad

# 3. Mark known good commit (e.g., last release)
git bisect good v2.3.0

# 4. Git checks out middle commit - test it
# Run your reproduction test
php artisan test --filter=OrderTotalTest

# 5. Mark result
git bisect good  # if test passes
git bisect bad   # if test fails

# 6. Repeat until Git finds the culprit commit
# Git will output: "abc123 is the first bad commit"

# 7. Examine the commit
git show abc123

# 8. End bisect
git bisect reset
```

### Automated Git Bisect

```bash
# Run automatically with test script
git bisect start HEAD v2.3.0
git bisect run php artisan test --filter=OrderTotalTest
```

### Git Bisect Tips

- **Choose good boundaries:** Bad = current, Good = last known working
- **Use automated testing:** Faster and more reliable
- **Check for flaky tests:** Bisect fails with inconsistent tests
- **Look at the diff:** Focus on changed lines in culprit commit

## Method 4: Stack Trace Parsing

Extract actionable information from error traces.

### PHP Stack Trace Structure

```
Fatal error: Uncaught TypeError: OrderService::calculateTotal():
Argument #1 ($items) must be of type array, null given,
called in /app/src/Application/UseCase/CreateOrderUseCase.php on line 45

Stack trace:
#0 /app/src/Application/UseCase/CreateOrderUseCase.php(45): OrderService->calculateTotal(NULL)
#1 /app/src/Presentation/Api/OrderController.php(32): CreateOrderUseCase->execute(Object(CreateOrderCommand))
#2 /app/vendor/symfony/http-kernel/HttpKernel.php(163): OrderController->create(Object(Request))
#3 /app/vendor/symfony/http-kernel/HttpKernel.php(75): HttpKernel->handleRaw(Object(Request))
#4 /app/public/index.php(25): HttpKernel->handle(Object(Request))
#5 {main}

thrown in /app/src/Domain/Service/OrderService.php on line 23
```

### Key Information to Extract

| Element | Value | Meaning |
|---------|-------|---------|
| Error Type | TypeError | Type mismatch bug |
| Message | Argument #1 must be array, null given | Null pointer issue |
| Thrown Location | OrderService.php:23 | Where error detected |
| Call Location | CreateOrderUseCase.php:45 | Where bad value passed |
| Root Investigation | CreateOrderUseCase.php:45 | Start here |

### Stack Trace Analysis Steps

1. **Read error message** - What type of error?
2. **Find thrown location** - Where was error detected?
3. **Find call location** - Where was bad value passed?
4. **Trace backward** - How did bad value get there?
5. **Find origin** - Where was value first set to bad state?

### Common Stack Trace Patterns

**Pattern: Null from Repository**
```
#0 Repository->find() returns null
#1 Service uses result without check
#2 Controller calls service
```
→ Fix in #1: Add null check

**Pattern: Type Coercion**
```
#0 Method expects int, gets string
#1 Request data not validated
#2 Controller passes raw input
```
→ Fix in #1 or #2: Add validation/casting

**Pattern: Missing Dependency**
```
#0 Service->method() called
#1 Container->get() fails
#2 Dependency not registered
```
→ Fix: Register dependency in container

## Method 5: Dependency Graph Analysis

Trace data flow through the application.

### Data Flow Tracing

```php
// Trace the flow of $orderId
1. Controller receives $orderId from Request
2. UseCase receives $orderId as Command property
3. Repository uses $orderId in SQL query
4. Database returns null (ID doesn't exist)
5. UseCase passes null to Service
6. Service throws NullPointerException
```

### Dependency Questions

- Where does the value originate?
- What transformations does it undergo?
- Where is it validated?
- Where could it become invalid?
- Who else uses this value?

### Call Graph Investigation

```bash
# Find all callers of a method
grep -r "->calculateTotal(" src/

# Find all places where variable is set
grep -r "\$items\s*=" src/

# Find all null assignments
grep -r "= null" src/Domain/
```

## Method 6: State Timeline Reconstruction

Rebuild the sequence of state changes.

### Timeline Template

```markdown
## State Timeline

T0: Initial state
    - Order::status = DRAFT
    - Order::items = []

T1: AddItemToOrder executed
    - Order::items = [Item(id=1)]
    - Expected: status stays DRAFT ✓

T2: SubmitOrder executed
    - Order::status = SUBMITTED
    - Expected: items preserved ✓

T3: PaymentReceived event
    - Order::status = PAID
    - BUG: items cleared unexpectedly ✗

T4: GetOrder query
    - Returns Order with empty items
    - User sees $0 total

Root Cause: PaymentReceived handler incorrectly reinitializes Order
```

## Investigation Checklist

### Before Starting
- [ ] Reproduce bug consistently
- [ ] Identify exact error message
- [ ] Note conditions when bug occurs
- [ ] Check if bug is environment-specific

### During Investigation
- [ ] Parse stack trace for key locations
- [ ] Apply 5 Whys technique
- [ ] Build fault tree if multiple possible causes
- [ ] Use git bisect if recent regression
- [ ] Trace data flow from origin to error

### After Finding Root Cause
- [ ] Verify fix addresses root cause, not symptom
- [ ] Check for similar bugs in related code
- [ ] Document root cause for team knowledge
- [ ] Consider if design change prevents recurrence

## Quick Reference: Where to Look First

| Bug Type | First Investigation Point |
|----------|--------------------------|
| Null pointer | Repository/Factory that creates the null |
| Wrong calculation | Input values, not calculation logic |
| Missing data | Event handler or background job |
| Intermittent failure | Shared state or race condition |
| After deployment | Git diff between versions |
| Only in production | Environment config or data |
| Only for some users | User-specific data or permissions |

More Debugging skills

← All Debugging skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY