Design Your Error States Before You Code
If you only design the happy path, someone decides the rest on the fly
Specs and tickets usually describe what happens when everything goes right: login succeeds, you land on the dashboard; a form submits, the list updates. What happens when the network drops, the user lacks permission, or they double-click submit is often left for whoever writes the code to decide on the spot.
Those on-the-spot decisions are inconsistent — one engineer throws an alert, another fails silently, a third leaves an English message on a Japanese screen. A meaningful share of bug reports trace back to exactly this: nobody decided what the error path should do. Design it before implementation starts, and this class of bug never gets created.
Build an error-path design table
Once the happy-path flow is written, fill in a table with four columns. Add one row per screen or API endpoint as you go.
1. Enumerate trigger conditions
"Network error" is too coarse. Break it down:
- Network disconnect / timeout
- Expired auth token
- Validation error (required field, format, length)
- Insufficient permission (accessing another user's resource)
- Duplicate submission / double click
- Server-side error (5xx)
2. The message shown to the user
"An error occurred" tells the user and support nothing. Pair what happened with what to do next.
3. What gets logged
Decide up front what's needed to reproduce: endpoint, status code, timestamp, request ID. Also decide now which values must never be logged because they contain personal data.
4. Whether it's retryable
Should this retry automatically, or does it need user action? Skip this decision and implementers tend to bolt on a "retry once, just in case" without thinking it through.
Example table
Condition | Message to user | Logged data | Retry? |
|---|---|---|---|
Network disconnect | "A network error occurred. Please try again shortly." | Endpoint / status code / timestamp | Yes (auto, up to 3x) |
Auth token expired | "Your session has expired. Please sign in again." | User ID / token expiry time | No (prompt re-login) |
Validation error | Name the specific field and how to fix it | Submitted payload (PII excluded) | No (needs input fix) |
Server error (5xx) | "A temporary problem occurred." | Stack trace / request ID | Yes (manual button) |
Review it before implementation, not after
Put this table on the agenda for every API and screen design review. If "how does this screen show a permission error?" comes up in review, it gets settled before a line of code is written — the most expensive time to ask that question is mid-implementation.
Skip the table and keep "figuring out errors while coding," and the same class of bug reappears in a slightly different shape on every screen. Build it once, and it becomes something you copy for the next feature — swap the conditions, keep the structure.
Putting this into practice with Bugoon
An error-path table doesn't tell you whether the app actually behaves that way — someone has to click through it. When a QA tester walks the app with Bugoon's widget, they can check each row against reality and file a report with a screenshot and recorded steps the moment something's off.
Error-path bugs, especially network-related ones, are hard to reproduce from a written report alone. Bugoon automatically attaches console logs and network errors to every submission, so the status code and timestamp from the "logged data" column show up in the actual report — the table and the report end up speaking the same language.
Streamline bug reporting for your team.
Bugoon is free to get started. Add one line of code to your site and transform how your team handles bugs.
Get Started