Skip to content

Debugging

The difference between a debugging session that takes five minutes and one that takes an hour is usually how much context you give Claude at the start. More context upfront means fewer back-and-forth rounds to locate the real issue.

Sharing Errors Effectively

The fastest path to a fix is giving Claude the full picture: the error, the stack trace, and how to reproduce it.

I'm seeing this error when I run npm test:
TypeError: Cannot read properties of undefined (reading 'userId')
at OrderService.createOrder (src/services/order.service.ts:47:23)
at POST /api/orders (src/routes/orders.ts:31:5)

Paste the complete error output, not a summary. Stack traces tell Claude exactly which file and line to examine. A paraphrased error (“it says something about undefined”) forces Claude to guess.

Three things that help:

  1. The exact command that triggers itnpm test, node src/index.js, curl -X POST ...
  2. Steps to reproduce — especially if the error only happens in certain conditions
  3. Whether it is intermittent — a race condition needs a different approach than a consistent crash

From Symptom to Fix

Vague bug reports work, but you will steer more. Specific ones often land on the first try.

# Works, but expect iteration
fix the authentication bug
# Specific — often correct on first attempt
The checkout flow is broken for users with expired cards.
Check src/payments/ for the issue, especially token refresh.
Write a failing test first, then fix it.

The second prompt gives Claude three things: the symptom, where to look, and how to verify the fix. Claude does not have to guess which of the five payment files to start with.

“Write a failing test first, then fix it” is the most important clause. It asks Claude to confirm the bug is real and reproducible before touching the fix, then verify the fix actually works — not just that the code looks plausible. This is the lightweight version of Verification-First Development.

Asking for Options Before Committing

For non-obvious bugs, it is worth seeing multiple approaches before choosing one.

suggest a few ways to fix the @ts-ignore in user.ts

Claude describes the tradeoffs of each option. Once you pick one:

update user.ts to add the null check you suggested

Two prompts instead of one, but you understand the fix and can explain it in the PR.

Plan Mode for Complex Bugs

Some bugs are not in one place. A symptom in the UI traces back through an API to a database query to a background job. Jumping straight to editing files in this situation usually means fixing the wrong layer.

Use plan mode to separate diagnosis from fixing:

  1. Press Shift+Tab twice to enter plan mode (shown as ⏸ plan mode on at the bottom)
  2. Describe the bug and let Claude analyze — read-only, no edits
  3. Review Claude’s diagnosis and proposed approach
  4. Press Ctrl+G to open the plan in your editor and refine it
  5. Approve the plan, then Claude implements
Terminal window
# Or start a session in plan mode directly
claude --permission-mode plan

Then:

Users are reporting that their cart empties randomly during checkout.
It seems to happen after they update their shipping address.
Analyze the checkout flow — src/checkout/, src/cart/, src/api/routes/ —
and identify the root cause before suggesting any fixes.

Claude maps out what it finds, explains the interaction it suspects, and proposes a fix. You approve or redirect before a single file is touched.

graph LR A([Paste error + context]) --> B([Claude locates root cause]) B --> C{Complex?} C -->|No| D([Apply fix directly]) C -->|Yes| E([Plan mode: diagnose first]) E --> F([Review plan]) F --> G([Approve → Claude implements]) D --> H([Verify with tests]) G --> H style A fill:#1e293b,color:#7dd3fc,stroke:#334155 style B fill:#1e293b,color:#a5b4fc,stroke:#334155 style C fill:#1e293b,color:#fcd34d,stroke:#334155 style D fill:#1e293b,color:#a5b4fc,stroke:#334155 style E fill:#1e293b,color:#a5b4fc,stroke:#334155 style F fill:#1e293b,color:#fcd34d,stroke:#334155 style G fill:#1e293b,color:#a5b4fc,stroke:#334155 style H fill:#1e293b,color:#86efac,stroke:#334155

Debugging Prompts for Specific Situations

TypeScript type errors:

I'm getting a type error in src/models/user.ts:
Type 'string | undefined' is not assignable to type 'string'
Fix it properly — no @ts-ignore or `as any` casts.

Test failures after a refactor:

After refactoring the UserService interface, these tests are failing:
[paste test output]
Update the tests to match the new interface, but verify the underlying
behavior is still being tested — don't just make the tests pass by removing assertions.

Intermittent failure:

This test fails roughly 1 in 10 runs. It looks like a race condition.
Here's the test: [paste]
Here's the output when it fails: [paste]
What's the likely cause and how should I fix it?

Production error from logs:

This error appeared in production logs overnight:
[paste log lines]
What's the likely cause? What context would help narrow it down further?

Related: Codebase Exploration for understanding the code before debugging. Prompting Patterns for @file references that focus Claude on the right files immediately.