Designing Analytics Screens That Fail Out Loud
On this page
The most expensive failure on an analytics screen is the one that looks like a correct answer. An empty chart reads as "nothing happened", a spinner that never ends reads as "still working", and a stale number reads as current. People act on all three.
This post covers four ways a screen can mislead and the small structural habits that stop each one. Two of them include a case from my own work.
Separate an empty result from a failed request
Ask for data and one of three things comes back: rows, an honest empty result, or a failure that the code turns into an empty result. Only the second one is "no data". If the code path that handles failure renders the same component as the empty state, the screen is telling a lie, and nobody sees it until a customer asks why a month is missing.
Give each request a result with distinct cases, loaded, empty and failed, and handle every case in one place. A new case then becomes a compile error instead of a blank panel.
Here is one case from my own work.
When a sign-on token expired, the request appeared to succeed and the page showed “no data” instead of an error. Using one token source and checking responses centrally made these failures visible and recoverable. See the RingCentral Events case study.
Give each data source its own state
A screen that loads several sources behind one shared flag fails quietly. The first source to finish decides what the person sees, and the slower ones look finished or missing. Each source needs its own loading, error and empty state, and the screen should say which part is still working.
Here is another case from my own work.
Several data sources loaded at once through one shared loading flag, so the first to finish could hide the others’ progress. Giving each source its own loading and error state fixed it. The setup is described in the integrations case study.
Say when a view is limited, not empty
A person without access to a segment, a date range that is only partly filled, an export capped at a size: each of these is "less than everything", not "nothing". Show the scope of the result next to the result. Say plainly what is hidden or missing, and what the person can do about it: ask an admin, narrow the range, or retry.
Put the unhappy paths in the test plan
Write the failure scenarios before the build, not after the first complaint: an expired session, a slow source, an empty range, a denied permission, partial data, and a retry after a failure. Run them by hand in a bug bash, and automate the ones that are cheap. A screen that has only been tried with good data has only been half tested.
A short checklist
- Every request has a loaded, empty and failed state, handled in one place.
- Expired or missing credentials raise a visible error, never an empty chart.
- Each source has its own loading and error state.
- The result shows its scope and how fresh it is.
- A retry sits beside the error it recovers from.
- The failure scenarios are in the test plan before launch.
For the wider picture of trust in data-heavy screens, read Designing Enterprise Dashboards People Can Trust.