Jako Heiberg
HomeInsightsMusingsPortfolioAboutContact
Jako Heiberg

From DBase III+ to edge computing.
The journey continues.

Pages

  • About
  • Portfolio
  • Resume / CV
  • Insights
  • Musings
  • Archive
  • Contact

© 2026 Jako Heiberg · Cape Town, South Africa · UTC+2

Built with React + Cloudflare Workers. No PHP was harmed.

Back to Insights
Insights

The Art of Debugging: Or How I Learned to Stop Worrying and Love the Stack Trace

Debugging is half detective work, half therapy session. Here's how to get good at both.

April 9, 2026
6 min read

The Art of Debugging: Or How I Learned to Stop Worrying and Love the Stack Trace

There is a particular kind of silence that falls over a developer's desk at 11pm. Not the comfortable silence of a good book or a sleeping house. This is the silence of a bug that should not exist, a system that was working fine ten minutes ago, and a git diff that looks completely innocent.

We have all been there. And if you haven't, you are either very new or very lucky — and your luck is coming.

Debugging is, at its heart, detective work. And like all good detective work, it rewards patience, clear thinking, and the willingness to question your most cherished assumptions — especially the one that begins with "there's no way that could be the problem."

Start with the Crime Scene

The first rule of debugging: read the error message. All of it. This sounds obvious, but you would be amazed how many developers — senior ones included — skim the first line and start Googling before they've absorbed what the stack trace is actually telling them.

The stack trace is a witness account. It is telling you exactly what was happening the moment things went wrong, in reverse chronological order. The bottom of the stack is where execution started; the top is where it fell over. Read it like a story, because it is one.

Once you've read the error, reproduce it reliably. A bug you can reproduce consistently is halfway solved. A bug you can only reproduce sometimes is a ghost story — technically real, but hard to reason about. Before you write a single line of fix code, you want a simple, repeatable case that demonstrates the problem. Ideally, something you can run in under ten seconds.

The Hypothesis Loop

Good debuggers are good scientists. They form hypotheses, test them, and update their model of the world based on what they find. The key word there is test — not "assume the fix worked" and ship it.

The loop looks like this:

  1. Observe the failure
  2. Form a hypothesis about the cause
  3. Predict what you'd see if the hypothesis were true
  4. Run a test (a print statement, a debugger, a unit test)
  5. Compare the result to your prediction
  6. Update your model and repeat

The temptation is to skip straight from step 2 to a code change. Resist this. You are not trying to make the symptom go away — you are trying to understand why it exists. Fix the cause, not the symptom, and you never see that bug again.

AI as Your Rubber Duck

The rubber duck debugging technique has been around for decades: explain your problem out loud to an inanimate object (traditionally, a rubber duck), and in the act of explaining, you often find the answer yourself. The duck doesn't help. You help yourself by being forced to articulate the problem.

AI has made this dramatically more powerful. Instead of a rubber duck that silently stares at you, you now have a rubber duck that asks questions, spots patterns across millions of codebases, and occasionally says "have you checked your timezone handling?" at exactly the right moment.

Modern AI coding assistants excel at debugging in a few specific ways. They can look at an error message and a code snippet and surface related issues they've seen in similar contexts. They can walk through your logic out loud if you paste it in and ask "does this look right?" And they are infinitely patient — they will not sigh audibly when you ask the same question three different ways.

What they're not good at is understanding your system in full. An AI doesn't know that your staging database has a slightly different schema than production, or that your colleague's recent migration had a subtle off-by-one error. That context lives in your head. The most effective AI-assisted debugging is a partnership: you bring the context, the AI brings the pattern matching.

The Nuclear Option: Binary Search

When you have no idea where the bug lives — the error is vague, the codebase is large, or the problem only shows up at the end of a long chain of operations — binary search debugging is your friend.

Comment out half the code. Does the problem persist? Then it's in the half that's still running. Restore, comment out a different half. Repeat until you've isolated the offending section to something small enough to reason about.

This feels crude. It is crude. It is also extremely effective, and experienced developers use it without shame.

Git bisect does this automatically for regressions: you tell it which commit was good, which commit is bad, and it binary-searches through your commit history to find the exact commit that introduced the problem. If you write atomic, well-described commits, this is one of the most powerful tools in the shed.

The Most Important Debugging Skill

After all the tools and techniques, the most important thing you can develop is the willingness to be wrong.

Most bugs exist because of a mistaken assumption. The code does what it says; it just isn't saying what you thought. When you're stuck, the question to ask is: "what am I assuming to be true that might not be?" Your understanding of the framework. The order of operations. What that function actually returns.

When you find the bug — and you will find it — take a moment to understand why your mental model was wrong. That understanding is the real product of debugging. The fix takes thirty seconds. The updated understanding stays with you for years.

The stack trace isn't your enemy. It's the crime scene photograph that breaks the case. Learn to read it well, and debugging becomes less of an ordeal and more of a puzzle. A frustrating puzzle, yes. But there's a particular satisfaction in solving it that no other part of software development quite matches.

Jako Heiberg

Software developer with 40+ years of building things that work. Full-stack, FastAPI, React. Based in Cape Town, working remotely, worldwide.

Related Posts

Insights

Vim From Scratch — Part 2: Modal Editing, and Why Modes Are a Feature

Every other editor lets you type text the moment you open it. Vim makes you ask for permission first. This sounds insane until you realise it's the reason Vim can do so much with so few keys.

August 26, 2026
5 min read
Insights

The Long Game: Staying Employable Without Burning Out

A software career is a forty-year marathon disguised as a series of sprints. Here is how to keep learning without chasing every shiny thing, and keep going without burning to the ground.

August 19, 2026
6 min read
Insights

Vim From Scratch — Part 1: Why a 1970s Editor Refuses to Die

Vim is older than most of the people using it, has a reputation for trapping newcomers who can't figure out how to quit, and is still one of the fastest ways to edit text ever built. Both of those things are true, and that's exactly why it's worth your time.

August 18, 2026
5 min read