Generative AI tools really love fallbacks
There are many kinds of fallbacks. Here are five:
- Using a default value if a caller doesn't provide it;
- Serving cached data if getting fresh data fails;
- Taking a best guess at an environment variable if it's not available;
- Trying something cheap first and then doing something expensive if that fails (this comes up a lot in parsing data that is probably, but not certainly, well-behaved); and
- Using a backup data source if a preferred one is not available (as during a migration).
Sometimes it's good to do this; it's often correct to be permissive in what you accept, and fallbacks help you do this. But I and many others have found that AI tools are overeager to do this. I've found my tools:
- Passing integration tests with a no-op when it can't reach a resource;
- Trying to "fall back to" trusting a JWT payload when verification fails;
- Handling a missing environment variable with a wild guess (or, worse, the value for the production system); and
- Filling in all sorts of default and null values in object-translation helper functions.
I could list many more. For now, I'm dealing with this in the straightforward ways: adding emphatic guidance to AGENTS.md, scanning for fallbacks as the code flies by, and telling different tools to look specifically for bad fallbacks.1
We are, as best I can tell, paying for our collective, long-running sins. Humans also use too many fallbacks: because we don't actually figure out our systems' behavior properly, because complicated chains of delegation and explicit case-handling are viewed as marks of professionalism, or just because we want to get the tests green. Happily, we're holding AI to a higher standard. I can't shake the feeling, however, that I'm a character in a novel, punished for my mistakes by facing a weird translated version of those very mistakes.
I'd guess that we will improve our collective understanding of when and when not to fall back, and our LLMs will do better at this out of the box. Until then, address the problem locally (by feeding guidance to your AI) and also make sure you look for manifestations of the problem: manually or systematically, by yourself or with AI.
Periodically asking an AI tool simply to "find a bug and fix it," or address a general problem (such as bad fallbacks), is surprisingly useful. But that's another post.↩