Error Handling
|

Handling Errors Gracefully: Letting AI Catch Everything So You Can Decide What the User Sees

Your app does something that can fail. Almost everything can, if you think about it: a payment that doesn’t go through, a file that won’t upload, a search that comes back empty, a save that hits a network hiccup halfway. Say you’re building a tool that lets freelance photographers deliver photo galleries to their clients. You ask your AI assistant to add error handling, because you know you’re supposed to, and a minute later it’s everywhere. Every function wrapped in a try/catch, every failure caught, every error logged and turned into a tidy message. You click around, nothing crashes, and you feel like you covered your bases.

Then a real client tries to download their gallery and the download fails, and what they see is a gray box that says “An error occurred.” That’s it. They don’t know if it’s their internet, your app, or something they did. They don’t know whether to wait, retry, or give up and email the photographer confused and a little annoyed. The app didn’t crash, so technically the error was handled. The person on the other end still got left standing in the dark. The careless version of this job isn’t asking AI to handle errors. It’s letting AI catch every failure and paper over all of them with the same generic apology, so nothing crashes and nobody knows what to do when something goes wrong.

What this job actually is

Handling errors is two jobs that get treated as one. The first is the catching: making sure that when something fails, your app doesn’t fall over. It notices the failure, keeps running, and doesn’t dump a wall of technical gibberish on the screen or take the whole page down with it. That’s mechanical work, and AI is genuinely good at it. It knows where failures tend to happen, it can wrap the risky operations, catch what they throw, and make sure a single hiccup doesn’t crash everything around it. Handing AI the catching is a fine idea; it’s thorough and it won’t forget the boring cases.

The second job is deciding what happens next, from the user’s side. When this particular thing fails, what should the person see, and what should they be able to do about it? Should the app quietly retry on its own? Tell them to try again? Point them somewhere for help? Reassure them their work is safe? Or is this a failure that should never happen quietly at all, one where you’d rather know immediately than have it swallowed by a catch block? That’s not mechanical. It’s a judgment call about what each failure means to the person hitting it and what you want them to do next.

Here’s the distinction that matters: AI can generate the catching, but deciding what the user sees and does is yours. A caught error is not a handled error. The value of good error handling comes from the moment things go wrong, which is exactly the moment a user decides whether they trust your app, and that moment is shaped entirely by what you chose to show them and offer them. AI can catch every failure perfectly and still have no idea which ones deserve a calm reassurance, which deserve a retry, and which should be raising an alarm instead of being hidden, because that depends on what the failure costs your user, and AI doesn’t know that unless you tell it.

How to delegate the catching

So lean on AI for the part it does well, which is finding the failure points and wiring up the catching so nothing crashes. The careless version is “add error handling,” which produces the blanket of identical gray boxes. The good version asks AI to do the mechanical work while you keep the decisions about what each failure means.

Ask AI to go through your app and identify the operations that can realistically fail: the network calls, the file operations, the places that depend on something outside your control. Ask it to catch those failures so a single one can’t take down the surrounding experience, and to make sure the technical detail of what went wrong gets recorded somewhere you can look later, separate from whatever the user sees. That separation matters: the developer needs the full story, the user needs a human sentence. Ask AI to build the plumbing that makes both possible.

Then you feed it your decisions. Once you’ve decided that a failed gallery download should offer a retry and reassure the client their photos are safe, AI is exactly the right tool to implement that cleanly and consistently everywhere it applies. You’re handing it the behavior you want and letting it do the careful, repetitive work of wiring that behavior in without missing a spot.

What you don’t do is ask AI to write the error messages and decide the responses on its own. The moment you say “handle the errors and show the user something helpful,” you’ve handed off the judgment, and AI will fill every case with the same safe, generic apology, because with no idea what each failure means to your user, a bland catch-all is the only thing it can honestly write. Keep the ask on catching and on implementing the responses you chose. Find the failures, keep them from crashing anything, record the details for me, and wire up the specific behavior I give you.

The judgment you keep

What the user sees and does when something fails is the call, and it’s yours because it turns on something AI can’t see: what each failure actually costs the person hitting it.

This is hard because catching everything the same way feels responsible and complete. Every failure is handled, nothing crashes, there’s a message for every case. But treating every failure identically is its own kind of neglect, because the failures are not identical to the person living through them. A search that returns nothing needs a friendly “no results, try a different word.” A payment that fails needs to be crystal clear that no money moved and they can safely try again, because the worst thing you can do is leave someone unsure whether they were charged. A save that fails needs to reassure them their work isn’t lost and quietly retry. And a few failures, the ones that mean something is genuinely wrong on your end, you might not want to smooth over at all, because a calm message to the user would hide a problem you need to know about right now. For the photographer’s app, a failed download is a mild annoyance you soften with a retry, while a gallery that saves but silently loses half the photos is a disaster you’d rather have blow up loudly than get quietly caught and hidden behind “everything’s fine.”

AI can’t make this call because it doesn’t know the weight of each failure in your product. It can catch the error and write a sentence, but it can’t feel the difference between the failure a user shrugs off and the one that makes them lose trust and leave, because that difference lives in what your app is for and what your users are counting on it to do. Get this wrong and you end up with an app that never crashes and never helps, where every problem produces the same shrug of a message and users slowly learn that when something goes wrong, your app has nothing useful to say. Deciding what each failure means, and what the person should do about it, is where error handling stops being defensive plumbing and starts being something a user can actually trust.

Before you ship this job

Here’s what good delegation looks like, and the line it can’t cross.

The sample prompt. Something real you might send:

I’m building FrameDrop, an app where freelance photographers deliver finished photo galleries to their clients, who view and download them. My main user on the client side is someone like Ben, who just paid for a wedding shoot and wants to download his gallery without any fuss. Go through FrameDrop and find the operations that can realistically fail: gallery loads, downloads, uploads on the photographer’s side, anything that depends on the network or storage. For each one, catch the failure so it can’t crash the surrounding page, and record the full technical details somewhere I can review later, separate from anything the user sees. Don’t write the user-facing messages or decide how each failure should behave yet; just give me the list of failure points you’ve wrapped, grouped by how serious the consequence looks, so I can decide for each one what the user should see and be able to do. I’ll hand you the specific behavior for each after that.

Use this and you get every failure caught and mapped, ready for you to assign real responses to. Copy it as-is and you’re catching FrameDrop’s failures instead of yours, and you’ve stopped right before the part that was yours to do. Ben’s painful failure is a download that dies mid-file; your app’s failures carry different weights, and the catching only becomes real handling once you’re the one deciding what each failure says and offers.

The part you can’t hand off is the response to each failure: what the user sees, whether they can retry, how you reassure them, and which failures you deliberately refuse to smooth over because you’d rather be alerted than have them hidden. That set of decisions is the job, and it’s the thing the prompt above deliberately stops short of asking AI to make.

How to check AI did its part: pick your most consequential failure, the one where a vague message would do real damage (the payment, the download, the save), and deliberately trigger it in a test. Then look at two things at once: what the user sees, and what got recorded for you. The user-facing side should tell a non-technical person exactly what happened and what to do next, in a sentence Ben could act on without emailing anyone. The recorded side should give you enough detail to diagnose it without reproducing it. If the user’s message is a generic “something went wrong” or the log is too thin to debug from, the handling isn’t done, no matter how many try/catch blocks are in place. The test isn’t whether the failure was caught; it’s whether the right person got the right information at the moment it mattered.

What you get for doing it this way

Go back to that gray box and the client left wondering whether to wait, retry, or give up. The difference between catching every error the same way and deciding what each one means is the difference between an app that merely survives its failures and one that stays helpful in the exact moment a user is most likely to walk away. When you let AI catch the failures and you decide what happens next, the person hitting a problem gets a clear next step instead of a shrug, and the failures that actually matter reach you instead of dissolving quietly into a catch block.

AI can catch every failure in your app and keep the whole thing from crashing. What each failure should mean to the person on the other end was always going to be your call, because only you know what they’re counting on and what it costs them when it breaks. That’s the job: let AI catch everything, then decide for yourself what’s worth telling the user and what’s worth telling you.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.