← all articles

Nothing Here Yet Is Not An Error

Nothing Here Yet Is Not An Error

If your app paints from a local copy first and then fetches live data, "there is nothing saved here yet" must be its own outcome, separate from "something went wrong". Collapse the two and a brand-new user gets an error message on a screen that is working exactly as designed. Worse, the people who see that message learn that your errors are noise, so they stop reading the ones that are real.

Two questions wearing one coat

The pattern is common in mobile work and increasingly everywhere else. To make a screen feel instant, you draw it from whatever the device already has, then reach out to the server and refresh. It's a good trade. The user sees something immediately, and the network gets to take its time.

The catch is that the first read has a question it can't always answer. Asked for the saved copy of a chart, the device may honestly reply that it has never stored one. That isn't a broken disk or a corrupt file. It's a first visit, or a fresh install, or a member who simply hasn't done the thing that produces data yet. The phone is telling the truth, and the truth is "no".

I came across exactly this recently in a small fix. A screen's first paint read only from the local copy. When nothing had been saved, the code that loaded the chart treated the "nothing saved" signal as a failure: it cleared the chart and put an error in front of the person. A moment later the live load would have filled the chart in anyway. So the sequence for a new user was an error, followed by a perfectly good chart, as though the app had shouted and then apologised.

The fix was a few lines. Catch that specific signal, stay quiet, and let the live load either fill the screen or report a real problem. The interesting part wasn't the code. It was that sibling screens in the same app already handled this case correctly, and this one had simply been written without anyone asking the question.

Why the quiet version is the honest one

It's tempting to think that showing an error is the safe default. If you're unsure, surface it. But an error message is a claim: something has gone wrong and you may need to do something about it. When that claim is false, you've misinformed the user, and you've done it at the worst moment, the first impression, before they have any reason to trust you.

There is a second cost, and it compounds. People calibrate quickly. If the red banner appears on screens that turn out fine, they learn to wave it away. Then the day a real failure shows the same banner, they wave that away too. You've spent your credibility on a case that never needed it.

If your team also reports errors shown to users into a monitoring tool, as I think most should, the false alarm costs you internally as well. The tool fills with entries that describe normal behaviour. Someone has to triage them, work out that they're harmless, and carry the memory that this particular entry can be ignored. That memory is fragile. It lives in one person's head until they leave, and then the next engineer investigates it from scratch. Noise in a monitoring tool is a tax paid repeatedly, usually by whoever is on call.

Making "not yet" a first-class result

The structural lesson is about how an operation reports its outcome. A function that returns data or throws gives you two outcomes, and anything that isn't data lands in the second one. Reading a local copy has at least three honest results: here is what I have, I have nothing, and something actually broke. If the code can only express two of them, the middle one will be forced into one of the others, and it will usually be forced into failure because that's the conservative choice.

Giving the middle case its own representation, whether that's a distinct result type, a specific signal, or just an empty value that callers are expected to handle, does more than fix one screen. It forces every caller to decide what "nothing yet" should look like in their context. For a chart, that might be a calm empty state. For a list, it might be an invitation to add the first item. For a settings page, it might be sensible defaults. Those are product decisions, and they're better made on purpose than inherited from whatever an exception handler happened to do.

It's also worth asking what the user is meant to feel. Someone opening a screen for the first time should feel welcomed, or at least not accused. "Nothing here yet" can be a gentle, even pleasant message. "Error" says they did something wrong or the product is flaky. Same underlying state, entirely different experience, and the difference cost nobody anything except attention.

The commercial angle

This might sound like polish, and in a sense it is. But first-run experiences are where retention is decided, and nobody files a support ticket saying "your app greeted me with a spurious error and I quietly lost confidence". They just don't come back. A fix that costs an afternoon and removes a bad first impression for every new person is some of the best value in a backlog, even though it never makes a roadmap.

There's a limit to the argument, and it's worth stating. Staying quiet is correct only because something else follows: the live load. If the app swallowed the "nothing saved" signal and then never fetched, the user would stare at a blank screen with no explanation. Silence is safe when a second step is guaranteed to speak. Before suppressing an error, I try to name exactly which later step will either deliver the data or report a real failure. If I can't name it, the error stays.

The habit worth keeping

When you find a screen showing an error for an expected state, don't stop at fixing that screen. Look at the ones beside it. In this case the neighbours already had it right, which tells you the knowledge existed in the codebase but hadn't become a shared habit. The most reliable way to spread it is to make the right behaviour the easy one, so that the next person writing a loader reaches for the "nothing yet" outcome without having to remember to.

Absence is information. An app that can tell the difference between "nothing here" and "I couldn't tell", and says only what it actually knows, is one people can believe when it does raise its voice.

Matthew Ratcliffe, software developer and architect, Ballarat
Senior Software Engineer & Architect

20+ years across the technology stack — from greenfield builds to brownfield rescues. Based in Ballarat, VIC, focused on AI, healthcare and high-risk data systems. Full resume →

Share your thoughts