Available for new projects & full-time roles

Let's Talk
All posts
The Best Debugging Skill Is Not Reading Stack Traces. It's Building Mental Models.
2025-08-01·9 min read·hot take

The Best Debugging Skill Is Not Reading Stack Traces. It's Building Mental Models.

The actual skill that separates fast debuggers from slow ones is mental model quality, here's what that means and how to build it.

debugging
software engineering
mental models
problem solving
developer skills
programming

Two engineers face the same bug. One resolves it in 20 minutes. The other spends three hours.

They have access to the same logs, the same debugger, the same codebase. The difference is not tooling. It's the quality of their mental model of the system.

TL;DR: The skill that separates fast debuggers from slow ones isn't reading stack traces, it's the quality of their internal mental model of how the system behaves. You build that model through four practices: reading code you don't own for its invariants, predicting outcomes before you verify them, tracing data instead of code, and teaching the system to someone else to expose the gaps in your own understanding. Debug from the model; the tools are just confirmation.


What a Mental Model Is

A mental model is your internal simulation of how the system behaves, what state exists where, how data flows between layers, what each component assumes about its inputs and guarantees about its outputs.

A high-quality mental model lets you form a precise hypothesis before you touch a debugger:

"This can only be failing in one of three places. The most likely one is the middleware that processes auth tokens, it strips the Authorization header before forwarding to the service, and if the token has expired the error won't be the 401 we'd expect, it'll be the empty-string check failing silently. Let me confirm."

A low-quality mental model leads to random log insertion, rerunning tests hoping for different results, and asking for help because you genuinely can't reason about where the failure could be.

Reading stack traces is a mechanical skill. Any competent engineer can do it. Building and maintaining accurate mental models is the actual leverage.

The Four Practices That Build Mental Models

1. Read Code You Don't Own

Not to understand every line. To understand the invariants: what does this module guarantee? What does it assume?

The documentation lies over time. The code doesn't. When you read a dependency's source and find // assumes non-null input, that's the mental model update that saves you three hours of debugging a null issue later.

2. Predict Before You Verify

Before you add a log line, write down (literally) what you expect to see. Then run it and compare.

This is uncomfortable because it forces accountability on your mental model. If you're wrong, you can't pretend you "kind of knew", you wrote down the wrong prediction and the gap is explicit.

The prediction-verification loop:

Form hypothesis: "The user.permissions array is empty at this point"
Add log:         console.log("permissions:", user.permissions)
Run:             See [ "read", "write", "admin" ]
Update model:    Permissions are populated, the issue is downstream

The engineers who skip the prediction step drift through debugging by observation. The engineers who commit to predictions maintain a sharp model.

3. Trace Data, Not Code

Most bugs are data bugs masquerading as logic bugs. Follow a specific piece of data from input to output and watch where it stops matching your expectation.

typescript
// Bug: user profile picture isn't showing in the UI

// Wrong approach: reading all the render code
// Right approach: trace the avatar URL from API to DOM

// Step 1: What does the API return?
// GET /api/users/123 → { id: "123", avatarUrl: "https://cdn.../abc.jpg" }

// Step 2: What does the Redux store contain after the API call?
// store.users["123"] → { id: "123", avatar_url: "https://cdn.../abc.jpg" }
//                                    ↑ naming mismatch! API uses avatarUrl, store uses avatar_url

// Step 3: What does the component receive?
// props.user.avatarUrl → undefined (reading wrong key)

// Bug found: serialiser normalised the key, component expects camelCase

The bug is in the data transformation, not the component logic. You find it by following the data, not by reading the component.

4. Teach the System

If you can explain how a system works to someone who doesn't know it, your mental model is solid. If you get three sentences in and realise you don't know what happens next, that's exactly where the bug is.

This is not a metaphor. When I'm stuck on a bug, I open a blank document and start explaining the system from scratch. The explanation always breaks down at the same point the code breaks down.

What High Mental Model Quality Looks Like in Practice

The best debuggers I've worked with rarely use breakpoints. They form a hypothesis, go directly to the most likely failure point, and confirm it. Their session looks like:

1. Read the bug report (2 minutes)
2. Form a hypothesis: "I think the issue is in X because Y"
3. Open exactly one file
4. Find the exact line
5. Fix it
6. Write the regression test

The debugging session of a low-model engineer:

1. Read the bug report (2 minutes)
2. Add console.logs throughout the feature
3. Run it, read the output
4. Add more logs
5. Try a random change
6. Open Stack Overflow
7. Try another random change
8. Accidentally fix it while doing something else
9. Can't explain why the fix works

The gap between these two profiles is not intelligence. It's accumulated mental model quality from the practices above.

Build the model. Debug from the model. The tools are just confirmation.


Want to go deeper on the engineering fundamentals that AI can't replace?

Mental model quality is exactly the kind of skill that separates engineers who use AI effectively from engineers who produce confident garbage with it. The AI coding tools post maps what that distinction looks like in a real PR review.

Hiring or have a project?

Let's build something that holds.

Full-stack engineering, system design, and legacy modernization. Available for freelance, contract, and full-time roles.

Keep reading