analyzing-root-causes
Root cause analysis with 5 Whys methodology for software problems. Triggers: 根本原因, root cause, 5 Whys, なぜなぜ分析, 対症療法, patch, symptom, 症状, 表面的, workaround, ワークアラウンド, 本質的, 応急処置, bandaid, quick fix.
When & Why to Use This Skill
This Claude skill leverages the 5 Whys methodology to conduct deep root cause analysis for complex software engineering challenges. It empowers developers to distinguish between surface-level symptoms and fundamental issues, facilitating permanent architectural fixes rather than temporary workarounds or 'band-aid' patches that increase technical debt.
Use Cases
- Investigating intermittent UI bugs, such as race conditions or double-submits, to identify logic errors instead of applying fragile 'setTimeout' workarounds.
- Analyzing recurring state synchronization issues in frontend frameworks to replace complex, nested side effects with clean, derived state patterns.
- Evaluating proposed 'quick fixes' during code reviews to ensure they don't mask deeper architectural flaws or introduce unnecessary system complexity.
- Systematically tracing software failures from observable symptoms down to design constraints to ensure robust, long-term stability and simpler code maintenance.
| name | analyzing-root-causes |
|---|---|
| description | > |
| Triggers | 根本原因, root cause, 5 Whys, なぜなぜ分析, 対症療法, patch, |
| context | fork |
| user-invocable | false |
Root Cause Analysis - 5 Whys Methodology
Target: Solve problems once and properly by addressing root causes, not symptoms.
Symptom vs Root Cause
| Type | Example | Result |
|---|---|---|
| Symptom Fix | Add setTimeout to wait for DOM | Works now, breaks later |
| Root Cause Fix | Use React ref properly | Permanent solution |
| Symptom Fix | Add flag to prevent double-submit | Complexity grows |
| Root Cause Fix | Disable button during submission | Simple, reliable |
Section-Based Loading
| Section | File | Focus | Triggers |
|---|---|---|---|
| 5 Whys | references/five-whys.md |
Analysis process, templates | 5 Whys, なぜなぜ |
| Patterns | references/symptom-patterns.md |
Common symptom→cause patterns | 対症療法, workaround |
Quick Checklist
Before implementing a fix, ask:
- Is this fixing the symptom or the cause?
- What would prevent this problem entirely?
- Can simpler technology (HTML/CSS) solve this?
- Is JavaScript truly necessary here?
- Will this fix introduce new complexity?
5 Whys Process
- Why does this problem occur? → [Observable fact]
- Why does that happen? → [Implementation detail]
- Why is that the case? → [Design decision]
- Why does that exist? → [Architectural constraint]
- Why was it designed this way? → [Root cause]
Example Analysis
Problem: Button click triggers action twice
- Why twice? → Click handler fires twice
- Why twice handler? → React re-renders during click
- Why re-render? → State update in click handler causes re-render
- Why state in click? → Using state for something that shouldn't be state
- Why using state? → Root cause: Treating imperative action as reactive state
Solution: Use ref instead of state for imperative flag, or disable button properly
Key Principles
| Principle | Application |
|---|---|
| Prevention > Patching | Best fix prevents the problem entirely |
| Simple > Complex | Root cause solutions are usually simpler |
| Ask Why | Don't accept the first answer |
| Progressive Enhancement | Can CSS/HTML solve this? |
Common Symptom Patterns
Timing Issues
// Bad: Symptom: setTimeout to wait for DOM
useEffect(() => {
setTimeout(() => {
document.getElementById("target")?.scrollIntoView();
}, 100);
}, []);
// Good: Root cause: Use React ref
const targetRef = useRef<HTMLDivElement>(null);
useEffect(() => {
targetRef.current?.scrollIntoView();
}, []);
State Synchronization
// Bad: Symptom: Multiple effects to sync state
useEffect(() => {
setFilteredItems(items.filter((i) => i.active));
}, [items]);
useEffect(() => {
setCount(filteredItems.length);
}, [filteredItems]);
// Good: Root cause: Derive state, don't sync
const filteredItems = useMemo(() => items.filter((i) => i.active), [items]);
const count = filteredItems.length;
Polling for Child State
// Bad: Symptom: Parent polling child for state
const childRef = useRef()
useEffect(() => {
const interval = setInterval(() => { childRef.current?.getValue() }, 1000)
}, [])
// Good: Root cause: Proper data flow (lifting state or callbacks)
const [value, setValue] = useState()
return <Child onValueChange={setValue} />
References
Core Principles
- @../../rules/development/PROGRESSIVE_ENHANCEMENT.md - Simple first
- @../../skills/applying-code-principles/SKILL.md - Simplest solution
Related Skills
enhancing-progressively- CSS-first approach often addresses root causesapplying-code-principles- Design principles prevent root cause issues
Used by Agents
root-cause-reviewer- Primary consumer of this skill