When the Error Never Comes
You will see errors. Not might. Will.
VS Code will underline something in red. Xcode will refuse to build. Whatever you are working in will eventually stop and tell you something is wrong, usually in a sentence written for someone who already knows what it means. If you can read those fluently, you are ahead of most people reading this. If you can't, it looks like noise with a line number attached.
The move is not to guess, and not to paste it back with "fix this" and hope. It is to ask, in plain words, without being embarrassed about it:
- What is this error, in language I would use?
- Why did it happen?
- Was it something I asked for, or a conflict with something we changed earlier?
- What is the smallest change that fixes it?
The third question is the one that earns its keep. It separates "the model got this wrong" from "the model did exactly what I said," and those two need completely different responses. One is a correction. The other is a lesson about how you asked. After enough rounds of that, you start heading off whole categories of these before they happen, which is most of what getting better at this actually consists of.
And that word "we" is deliberate. The code came out of a conversation, so when it is wrong, it is wrong because of something in that conversation. The useful question is which part, not whose fault. The shipping, though, is yours alone.
Now the part worth sitting with: those errors are the good ones. They are loud, they arrive before the thing ever ran, and they cost you nothing but an afternoon. A build that refuses to build has done you a favour.
This post is about the other kind. The run that finishes, says nothing alarming, and is wrong anyway.
A smoke alarm that has never gone off is either proof that nothing has burned or proof that the battery is flat, and from where you are standing those two look exactly the same. Silence is not information. It only becomes information after you have pressed the test button. Most AI-written code arrives with the battery out.
Five words for that, below. I have arranged them the way a problem actually travels: how the code should behave when something goes wrong, the way it usually behaves instead, and how you find out either way. That is a rough shape rather than a rule, and if you have already been bitten by one of these you will want to skip to it.
1. Fail fast
Stop immediately and loudly instead of limping on with bad data. Every red underline in your editor is this idea working correctly: the problem was caught at the earliest possible moment, when it was cheapest to fix.
The model's instinct runs the other way. Asked to write something that reads a file, it will write something that reads a file, and if the file isn't there it will very often carry on with an empty value rather than stop. It is optimizing for code that completes. You want code that refuses.
The distinction matters more than it sounds. A script that stops on the first bad row costs you one fix. A script that skips bad rows and keeps going costs you a result you half trust and no idea which half.
Turn it into a prompt: "Where in this would bad or missing data get carried forward instead of stopping the whole thing? Make it stop instead."
2. Silent failure
The failure that doesn't announce itself. The script copies forty of your fifty files and exits cleanly. The upload skips the ones with unusual names and reports success. Nothing turns red. Nothing is wrong, as far as anything on your screen is concerned.
This is the signature bug of writing code you did not write. When you build something by hand, you carry a rough map of where it is thin, and that map is what makes you suspicious at the right moments. Working from generated code, you have no map. Your only signal that something went wrong is whether the thing complained, which is precisely the signal a silent failure doesn't send.
The defence is to decide in advance what you will check. Not "did it run" but "did it do the job," expressed as something countable. Fifty files in, fifty files out.
Turn it into a prompt: "List the ways this could fail without printing anything at all. For each one, make it print something."
3. Error handling
What the code does when something goes wrong. There are two common answers, and the model tends to pick whichever produces fewer complaints.
The first is nothing at all, which at least fails honestly. The second is worse: a catch block that swallows the problem and moves on. In Python it looks like except: pass, and variations of it exist in every language. It is the single most destructive pattern a beginner can accept without noticing, because it converts a loud failure into a silent one. It takes the one thing that was going to save you and throws it away.
You are not looking for the absence of error handling. You are looking for error handling that keeps the evidence.
Turn it into a prompt: "Show me every place this catches an error. For each one, tell me what it does with it, and whether I would ever find out."
4. Logging
The breadcrumbs that let you reconstruct what happened after it happened. Print statements count. This does not have to be sophisticated to be the difference between ten minutes and an afternoon.
Here is the uncomfortable part. Code you wrote yourself needs less logging, because you remember roughly what it does and can guess where to look. Code you did not write needs more, and it usually has less, because nobody asked for any. The gap between how much you need and how much you have is widest exactly where you are least equipped to close it.
The test to apply: if this ran while you were asleep and produced the wrong answer, is there anything at all you could read afterward to work out why?
Turn it into a prompt: "Add logging that would let me reconstruct what happened if this ran overnight and I wasn't watching."
5. Race condition
A bug that only shows up when two things happen in an unlucky order. It works. Then it doesn't. Then it works again, same input, no changes. That pattern is the tell, and it is worth knowing the name because it is one of the few problems where "it only happens sometimes" is a real diagnosis rather than a shrug.
Models write these fairly readily, and the reason is structural. They reason about code one line after another, and races live in the space between the lines, where two things you thought were sequential turn out not to be. Anything doing several things at once is a candidate: downloads, file writes, anything described as asynchronous.
You will probably not fix one of these yourself. Naming it is still worth something, because it stops you from spending a week looking for a bug in logic that is fine.
Turn it into a prompt: "Is anything here happening at the same time as anything else? What breaks if they finish in the wrong order?"
What "it works" is missing
"It works" sounds like a complete sentence and isn't. Works on what input. Checked by whom. Measured how. Every silent failure I have described lives in the gap between that phrase and the three things it leaves out.
The habit worth building is small: before you run something, say out loud what you will look at afterward to decide whether it worked. Not the absence of an error. A number, a count, a file you open. If you can't name that thing in advance, the code finishing tells you nothing at all, and you are back to standing under a smoke alarm that has never once gone off.
Guardrail #7
A clean run is not evidence.
Before you run it, name the one thing you will check afterward to prove it did the job. A count, a file, a number you can compare. If you can't name it before you run, finishing tells you nothing.
This is the fourth stop in a series on the words that change what the AI hands back. Earlier: the terms worth knowing before you type a prompt, the questions to ask once the code comes back, and the six to ask before you run it for real.
Receipts
- Fail Fast · Jim Shore, IEEE Software, on stopping immediately rather than continuing in a bad state
- Errors and Exceptions · the official Python tutorial, on what catching an error actually does
- Monitoring Distributed Systems · Google's Site Reliability Engineering book, on why a system that fails quietly is the hard case
- Data Race Detector · Go documentation, with a plain description of what a race actually is
Comments
Post a Comment