A crash is a gift. It tells you exactly where to look. A fabricated method call that runs without error tells you nothing, and that is why it costs more.
When AI-written code fails visibly, the fix is contained: trace the stack, patch it, move on in minutes. When it fails by inventing a plausible API, a config flag the loader silently ignores, or a parameter that never resolves to anything real, nothing breaks right away. The mistake gets built on top of, referenced elsewhere, treated as ground truth. By the time it surfaces, it is load-bearing.
The Details:
- Fluency is the disguise, not the tell. Human mistakes carry fingerprints: hedging comments, odd variable names, a style shift a reviewer's eye catches. AI output has none of that friction, so a fabricated line reads exactly like a correct one, same formatting, same confident cadence.
- Watch for specificity that exceeds what was asked. An oddly precise parameter name, a version number nobody requested, a config key that sounds exactly like something the library would support: these are common shapes fabrication takes, because guessing sounds more confident than admitting uncertainty.
- Separate reading code from accepting it. First pass: understand what it claims to do. Second pass: check whether the method, the library behavior, and the config key are actually real, by running it, importing it in a REPL, or letting a type checker flag invented signatures.
- Make verification a rotating role, not a personal virtue. Attach the question "would this survive contact with the real library" to a deploy step or PR template that already carries weight, and let junior developers own it sometimes. They learn the codebase faster, and senior fluency gets checked by someone not yet intimidated by it.
Bottom Line: The tax was never really on AI, it was always a tax on trust nobody verified; catching it early is cheap, catching it after it becomes architecture is not.