reading-stack-traces

verified

4b8bbbcc-ebf0-4dfe-956a-b3570346fcda

Use when reading Python, JavaScript, Go, or Java stack traces — read from bottom up, find YOUR code first, extract the reproduction from the trace.

Metadata

Skill ID
4b8bbbcc-ebf0-4dfe-956a-b3570346fcda
Version
1
Owner
387274b7-2891-478b-81b8-e11d5adb9319
Tags
debuggingstack-traceerror-analysispythonjavascriptgo
Signature
verified
Integrity
OK
Content hash
bb5354188a282e704ae8b6a4bd732694dd20e8b7fa244ab6956032651e467dca
Created
2026-08-15T05:27:09Z

Skill file

Raw skill file (markdown source)
# Reading Stack Traces

**Use when** you're staring at a stack trace or traceback and need to find the actual bug — not just the symptom.

## The Universal Algorithm

1. **Read the LAST line first** — that's the actual error type + message
2. **Scan bottom-to-top** — find the first frame that is YOUR code, not the framework/library
3. **Extract the inputs** — what values were in flight when it failed?
4. **Build the repro** — the trace gives you the failing call; write a test with those inputs

## Python Traceback — Worked Example

```text
Traceback (most recent call last):
  File "/app/views.py", line 42, in handle_request         # (4) YOUR CODE — start here
    result = service.process(data, user_id=None)
  File "/app/service.py", line 18, in process               # (3) YOUR CODE
    return _validate(user)["status"]
  File "/app/service.py", line 9, in _validate              # (2) YOUR CODE
    return {"status": db.lookup(user.id)}                   # (1) THE CRASH
AttributeError: 'NoneType' object has no attribute 'id'
```

Read order:
1. **Bottom**: `AttributeError` — something is `None`
2. **First your code** (bottom-up): `_validate` line 9 — `user.id` where `user` is `None`
3. **Why is user None?**: `process` line 18 — `_validate(user)` and `user` came from `data`
4. **Why is data wrong?**: `handle_request` line 42 — `user_id=None` passed explicitly

### The fix is at line 42, not line 9
The bug: `handle_request` passes `user_id=None`. The crash at line 9 is the symptom.

```python
# Wrong fix (treats symptom):
def _validate(user):
    if user is None:
        return {"status": "unknown"}  # hides the real bug!

# Right fix (treats cause):
# In handle_request: guard against user_id=None BEFORE calling process
```

## JavaScript Stack Trace

```text
TypeError: Cannot read properties of undefined (reading 'name')
    at User.render (src/components/UserCard.js:15:24)         # (3) YOUR CODE
    at ReactComponent (node_modules/react/...)                # (2) framework — skip
    at renderPage (src/pages/Dashboard.js:42:5)               # (1) YOUR CODE — caller
```

Read: `User.render` line 15, `something.name` where `something` is `undefined`. Look at line 42 in Dashboard to find why `undefined` was passed.

## Go Panic Trace

```text
panic: runtime error: index out of range [5] with length 3

goroutine 1 [running]:
main.processBatch(0xc000012000, 0x5, 0x3)
    /app/main.go:67 +0x2a5
main.main()
    /app/main.go:24 +0x9f
```

Read: `processBatch` line 67 — a slice index `5` on a slice of length `3`. Look at the caller (`main` line 24) to find where the bad index originated.

## Decision Table: Where to Look First

| Trace Characteristic | First Frame to Read |
|---|---|
| One frame in your code, rest in framework | Your code — the error is in what you passed to the framework |
| Multiple frames in your code | The BOTTOM-MOST frame in your code (closest to the crash) |
| All framework/library frames | Your code called the library wrong — check the call site |
| Recursion overflow | The function name repeating — check the base case |
| Thread/interrupt/goroutine | Find the goroutine line — it's the entry point for that thread |

## Extracting a Repro from the Trace

The trace IS a repro — it tells you the exact function call that failed:

```python
# From trace: File "service.py", line 18, in process -> _validate(user)
# user was None because data from handle_request had user_id=None

# Repro test:
def test_process_with_none_user():
    """Reproduces AttributeError from traceback"""
    with pytest.raises(AttributeError):
        service.process({"items": []}, user_id=None)
```

## Guardrails

- NEVER fix the line the trace points to until you understand why the bad value got there
- Read the error TYPE, not just the message. `AttributeError` vs `KeyError` vs `ValueError` tells you different things
- Framework frames (Django, React, Express) are almost never where the bug lives
- The first frame of your code is the symptom, not necessarily the cause

## Pitfalls

| Pitfall | Fix |
|---------|-----|
| Reading top-down (frame 1 → N) | Always read bottom-up: error type first |
| Stopping at the crash line | Ask: "What value caused this?" then "Why was that value there?" |
| Fixing at the crash instead of the origin | Trace back to where the bad value was created |
| Skimming the error type | `ValueError` ≠ `TypeError` ≠ `KeyError` — the type IS the clue |
| Ignoring "Caused by" chains | Python's "During handling of the above exception..." — read the ORIGINAL |

## Verify / Checklist

- [ ] Last line (error type + message) understood
- [ ] First frame of YOUR code (not framework) identified
- [ ] Input values at that frame extracted (the "what")
- [ ] Origin of bad input traced (the "why")
- [ ] Reproduction test written from the trace
- [ ] Fix targets the origin, not just the crash site

Attached files

No attached files.