Contents

"Learning to Code with AI" Series — Article 6/7
RSS
RSS sends new articles to the reader of your choice, without an algorithm or newsletter.
TL;DR
Copying an error into an agent and accepting the first fix is quick. It doesn’t necessarily teach you how to debug. The right loop involves reading the symptom, reproducing the problem, formulating a hypothesis, observing what confirms or rules it out, then asking the AI to challenge your diagnosis.
Making an Error Disappear Isn’t Always Solving It
An error appears in the terminal or browser. The reflex has become almost mechanical: copy the message into Claude Code or Codex, ask for a fix, accept the suggested change, and move on.
The error disappears. You feel like you’ve debugged.
Sometimes, that’s true. Often, you’ve only moved the problem or masked its symptom.
Debugging isn’t a collection of fixes. It’s a way to reduce uncertainty until you understand why the system behaves that way. This method may seem slower when you only look at the time spent on the first error. It becomes much faster when a similar error appears the following week and you already recognize its family.
Let’s take a realistic situation in our mini-dashboard. The API returns a response where the CPU metric is null. The component, however, assumes it always receives a number and attempts to format it. The page crashes.
The quickest fix might be to replace the missing value with zero. The screen no longer crashes. But the dashboard now shows a CPU load of 0%, when the data is actually unknown. Technically, the crash is gone. Functionally, you may have just created false information.
The problem, therefore, isn’t just the failing line. It could lie in the API contract, response validation, the type used, or how to display an unavailable state. This is precisely where human reasoning must remain present.
Start with a Hypothesis, Not a Request for a Fix
Before asking the agent for help, take a few minutes to read the entire error. Look at the file, the line, the stack trace, and the exact steps to reproduce it. Then, try to articulate what you think is happening.
In our example, the hypothesis could be simple: "The external response isn’t validated before reaching the component, so cpu can be null while the rendering expects a number."
This statement doesn’t need to be correct. It just needs to be verifiable.
A hypothesis turns a vague error into an investigation. You then know what observation to look for: the raw API response, the value after validation, then the value received by the component. Each observation eliminates some possible causes. You no longer need to add logs everywhere or ask the AI to guess the entire architecture from an isolated stack trace.
The prompt changes completely:
Here’s the error, the reproduction steps, and my hypothesis.
Do not modify any files.
First, evaluate my hypothesis. Indicate the most useful observation to confirm or rule it out.
Suggest at most two alternative causes, ranked by probability.
Distinguish observed facts from your deductions.
The agent is no longer a "fix" button. It becomes a second set of eyes. It can spot an overlooked lead, suggest a more discriminating observation, or save you from wasting an hour on an unlikely cause. But it works with your reasoning, not in place of it.
Logs Aren’t a Strategy
When stuck, you often see a flurry of console.log statements. That’s understandable. A log gives the impression of taking action. Yet a log is only useful if it answers a question.
"What value comes out of validation?" is a useful question. "Does the API call respond before rendering?" is another. "Let’s add logs in every file" doesn’t reduce anything. It just adds noise where you might miss the important information.
An agent can help you instrument the code, but always ask it what question each addition is meant to clarify. Also ask it to flag sensitive data: a token, an email address, a full API response, or customer information has no place in production logs.
When the context allows, a breakpoint in a debugger is often more precise. It lets you observe a value at the exact moment it changes, instead of reconstructing the sequence afterward. The tool matters less than the discipline: observe one boundary at a time.
A Fix Must Respect the Contract, Not Just the Symptom
Back to our missing CPU metric. The agent might suggest this:
const cpu = metrics.cpu ?? 0
This code is short. It may even seem cautious. But it makes a silent business decision: it conflates unavailable data with zero load.
The right fix depends on what the system actually promises. If null is an expected response, the interface should clearly show the measurement is unavailable. If this value should never occur, the response should be rejected at the boundary and the incident made visible. If it comes from an unstable API, you might need to preserve the last known value—but only if that rule is explicitly defined.
These are product and architecture decisions before they’re syntax decisions. The AI can suggest multiple treatments. It can’t silently choose the one that changes the meaning of the data.
After the fix, add a test that reproduces the scenario. Not just to check a "coverage" box, but because you want to prevent this same error from returning in another form. Then note, in a few lines, your initial hypothesis, the observation that settled it, and the safeguard you added. This record becomes a mental library. Over time, you recognize validation errors, asynchronous state issues, caching problems, configuration mistakes, or permission issues more quickly.
Keep Some Moments Without Assistance
Avoiding AI for a short session isn’t a nostalgic exercise. It’s a resilience test.
Once or twice a week, take a small error and try to diagnose it alone for twenty minutes. You can check the documentation, use the debugger, write a test, or examine the diff. Only then ask the agent to review your approach or suggest a lead if you’re still stuck.
The goal isn’t to prove you can do everything without tools. No serious developer works that way. The goal is to maintain the ability to act when the agent lacks context, produces a confident but wrong answer, or is simply unavailable.
The more precise your diagnosis, the more effective the AI becomes. You give it a scope, facts, a hypothesis, and a question. It no longer has to invent the rest of the system. That’s the real gain: less guesswork, fewer cosmetic fixes, and an understanding that stays with you after the conversation.
In the final article, we’ll turn this method into a concrete 30-day progression.
