Debugging with Claude

Claude in VS Code: Pair Programming

Chapter 5  ·  Debugging with Claude

Debugging is where having a knowledgeable second pair of eyes pays off immediately. Claude can read a stack trace, explain what went wrong, suggest root causes, and propose a fix — often faster than you could work through it alone. But there's a discipline to debugging with AI: the quality of Claude's diagnosis is directly proportional to the quality of the information you give it. This chapter covers what to send, how to ask, and when to reach for the debugger instead.

Reading a Stack Trace with Claude

A stack trace tells a story — but reading it bottom-up (where the error originates) is different from reading it top-down (how you got there). Claude is good at translating the trace into plain language and pointing at the line that matters. The key is sending the whole trace, not just the error message.

Python traceback — annotated
Traceback (most recent call last):
  File "app/api/routes/orders.py", line 47, in create_order entry point
    result = order_service.process(payload)
  File "app/services/order_service.py", line 112, in process
    user = db.query(User).filter_by(id=payload.user_id).one()
  File "sqlalchemy/orm/query.py", line 2691, in one read from here down
    raise NoResultFound()
sqlalchemy.orm.exc.NoResultFound: No row was found for one() actual error

When sending a trace to Claude:

  • Include the full trace — not just the final error line. The frames above it show how the code got there.
  • Include the relevant source lines — the trace shows line numbers, but not the surrounding context. Open the file and paste the function Claude is being asked to diagnose.
  • Describe what you were doing — "this happens when I try to create an order for a user who signed up yesterday." Conditions that trigger the bug are often the key to understanding it.

What Information to Send

Always include
  • The complete error message and stack trace
  • The function or block where the error occurs
  • What you were doing / what input triggered it
  • What you expected to happen
Include if relevant
  • Recent changes to the code ("I refactored this yesterday")
  • The environment it fails in vs works in
  • Any related function that calls or is called by the failing code
  • Data shape or sample values that trigger the error
Helpful extras
  • What you've already tried and ruled out
  • Whether it's intermittent or consistent
  • Library / framework versions if version-specific
  • Logs from immediately before the error
Don't omit
  • The inner-most exception (sometimes wrapped)
  • The file and line number from your code (not the library)
  • Type information if it's a type error
  • The actual vs expected value if it's an assertion

Explain vs Fix — Know Which to Ask For

There's an important difference between asking Claude to explain a bug and asking it to fix a bug. Both are useful, but they serve different purposes and the one you choose affects how much you learn.

Ask Claude to explain

You understand the root cause before any code changes. Better for: bugs in code you're unfamiliar with, subtle logic errors, or anything where you want to stay in control of the fix.

What's causing this error? Explain the root cause — don't write a fix yet, I want to understand what went wrong first.
Ask Claude to fix

Fastest path to a working change. Better for: well-understood errors (typo, missing import, off-by-one), boilerplate fixes, or when you're under time pressure.

Fix this bug. The error is a NoResultFound when user_id doesn't exist in the DB — handle that case by returning a 404 HTTPException.
Explain first for unfamiliar code
If you're debugging code you didn't write and don't fully understand, always ask for the explanation first. Accepting a fix you don't understand means you'll hit a variant of the same bug again — and Claude won't be there to fix it in production.

Bug Categories and How to Ask

Exception / crash
Here's the full traceback and the function at line 112. What's causing the NoResultFound and how should it be handled?
Paste the full trace + the relevant function. Don't summarise the trace — send it verbatim.
Wrong output
This function returns 42 when I call it with input X, but I expect 38. Here's the function — can you trace through what it computes for that input?
Give Claude both the actual and expected value, plus a concrete input to trace through.
Intermittent failure
This fails maybe 1 in 10 times with a race condition. Here's the code path. What could cause non-deterministic behaviour here?
Claude will point at shared state, async timing, and unguarded reads. Follow up with "how would I reproduce this reliably?"
Performance regression
This query ran in 40ms yesterday. After I added the LEFT JOIN it takes 4 seconds. Here's the query and the EXPLAIN output. What's causing the slowdown?
Always include EXPLAIN / EXPLAIN ANALYZE output for query performance issues. Without it Claude is guessing.
Silent failure
This function returns successfully but the record isn't being saved. No exception is raised. Here's the function — what could cause a silent no-op?
Silent failures are often un-awaited coroutines, swallowed exceptions, or a session that isn't being committed.
Type / import error
I'm getting `AttributeError: 'NoneType' object has no attribute 'email'`. Here's the line and the function that creates the object. When would `user` be None here?
Ask Claude when the value could be None rather than how to guard against it — understanding the cause prevents the same bug downstream.

Claude vs the Debugger — When to Use Which

Reach for Claude when… Reach for the debugger when…
You have a stack trace and want it explained You need to inspect actual runtime values at a specific line
The bug is in logic you can read statically The bug only manifests under specific timing or load conditions
You want to understand why the code fails, not just where You need to step through a complex execution path frame by frame
The error message is cryptic and needs translation You're dealing with a memory issue, thread race, or async timing bug
You want to brainstorm possible root causes You need to watch a variable change across many iterations
The bug is in a third-party library and you want to understand its behaviour The execution path is long and branching and you can't mentally model it

The two tools complement each other. A common workflow: use Claude to identify the likely cause and the suspect lines, then set a breakpoint at exactly those lines in the debugger to confirm. This is faster than stepping through from the start.

When Claude's Diagnosis Is Wrong

Claude can misdiagnose a bug — especially when the cause is environmental (a specific data state, a platform difference, a version incompatibility) rather than visible in the static code. If Claude's suggested fix doesn't resolve the problem:

  • Tell Claude what happened — "I tried that fix and still get the same error. Here's the new trace." This is the most important thing you can do — don't start over, iterate.
  • Add more context — if Claude missed something, it's usually because you didn't include it. What's in the database? What's the actual value of the variable? What changed recently?
  • Ask for alternative hypotheses — "If that's not the cause, what else could explain this?" Claude will generate other candidates to investigate.
  • Try rubber duck debugging — ask Claude to ask you questions: "Ask me questions to help diagnose this." Often the act of answering surfaces what you'd forgotten to include.
The quick-fix trap
When Claude confidently proposes a fix, it's tempting to apply it and move on if the error disappears — without understanding what caused it. Resist this. A fix you don't understand is a bug that will return in a different form. Take thirty seconds to read Claude's explanation even when you're under pressure.
Next — Chapter 6: Writing Tests
Asking Claude to write unit tests, integration tests, and edge cases. How to brief Claude on your testing framework and style, how to get tests that actually cover the right behaviour, and how to use Claude to find the edge cases you haven't thought of yet.