Error & Feedback Standard
Error types and display locations, field-level errors, form API errors, page-level errors, API error code mapping, no silent failures rules.
No error is silent. No action is invisible. Every failure tells the user what happened and what to do next.
Contents
| # | Section |
|---|---|
| 1 | Error Types & Display Locations |
| 2 | Field-Level Errors |
| 3 | Form API Errors |
| 4 | Page-Level Errors |
| 5 | API Error Code Mapping |
| 6 | Empty States |
| 7 | Destructive Action Confirmation |
| 8 | Network Errors |
| 9 | Auth Errors |
| 10 | Message Standards |
| 11 | No Silent Failures |
1. Error Types & Display Locations
| Error Source | What It Is | Where to Show It |
|---|---|---|
| Client-side validation | Required field, format, length | Below the field (field error) |
| API field error | Duplicate, constraint failure | Below the field + form banner |
| API business rule | Permission, state conflict | Form banner or inline alert |
| API server error | 500, unexpected | Form banner or page error banner |
| Page load failure | Data could not be fetched | Full page error state with retry |
| Network failure | No connection, timeout | Toast or inline banner |
| Auth expiry | Session expired | Redirect to login (not a blank page) |
2. Field-Level Errors
3. Form API Errors
4. Page-Level Errors
— Friendly message: "Could not load projects. Please try again."
— Retry button (re-triggers the original fetch)
5. API Error Code Mapping
Map backend error codes to user-facing messages on the frontend. Never show raw codes.
| Backend Code | User-Facing Message |
|---|---|
VALIDATION_ERROR |
Show the specific field message from the error detail |
DUPLICATE |
"A [entity] with this name already exists." |
NOT_FOUND |
"This item was not found. It may have been deleted." |
FORBIDDEN |
"You don't have permission to do this." |
AUTH_REQUIRED |
Redirect to login |
BUSINESS_RULE_VIOLATION |
Show the specific reason from the error detail |
SERVER_ERROR |
"Something went wrong. Please try again." |
| Network / no response | "Connection lost. Check your internet connection." |
// Standard pattern for parsing Supabase/backend error codes
const { data, error } = await supabase.rpc('create_project', params);
if (error) {
const code = error.message.split(':')[0].trim();
const msg = error.message.split(':').slice(1).join(':').trim();
switch (code) {
case 'VALIDATION_ERROR': return showFieldError(msg);
case 'DUPLICATE': return showFormError('A project with this name already exists.');
case 'FORBIDDEN': return showFormError("You don't have permission to do this.");
case 'NOT_FOUND': return showFormError('This item was not found. It may have been deleted.');
case 'BUSINESS_RULE_VIOLATION': return showFormError(msg);
default: return showFormError('Something went wrong. Please try again.');
}
}
6. Empty States
NO DATA EXISTS
[ ] Illustration or icon — not just text
[ ] Specific message: "No projects yet." — not "No data." or "Empty."
[ ] Call to action: "Create your first project" button or link
SEARCH RETURNED NO RESULTS
[ ] "No results for '[search term]'."
[ ] "Try a different search term."
[ ] Clear search button visible
FILTER RETURNED NO RESULTS
[ ] "No [entities] match your current filters."
[ ] Shows what filters are active
[ ] "Clear all filters" button prominent
COMBINATION (search + filters active)
[ ] "No results for '[term]' with these filters."
[ ] Both "Clear search" and "Clear filters" available
RULE: Never show a blank table body or an empty list without a message.
7. Destructive Action Confirmation
Before any irreversible action, show a confirmation dialog.
LOW RISK (Archive, soft actions)
Title: "Archive Project?"
Body: What happens + whether reversible: "This project will be hidden from your workspace. You can restore it later."
Buttons: "Cancel" (left), amber or red action button (right): "Archive"
MEDIUM RISK (Delete a record)
Title: "Delete Project?"
Body: Item name + consequence: "'Marketing Q1' will be permanently deleted along with all its tasks."
Body: "This action cannot be undone."
Buttons: "Cancel" (left), "Delete Project" — red/danger (right)
HIGH RISK (Delete account, all data, bulk delete)
Same as medium +
Type-to-confirm input: "Type DELETE to confirm"
Submit button: disabled until input matches exactly (case-sensitive)
Buttons: "Cancel" (left), "Delete Everything" — red/danger, disabled until confirmed (right)
8. Network Errors
9. Auth Errors
10. Message Standards
TONE
[ ] Friendly and specific — not technical
[ ] No "Error", "Failure", "Exception" as the full message
[ ] No exclamation marks on error messages
[ ] Past tense for completed: "Project saved." "Changes discarded."
[ ] Present tense for ongoing: "Saving..." "Deleting..."
[ ] No ALL CAPS in messages
SPECIFICITY
Good: "Password must be at least 8 characters."
Bad: "Invalid input."
Good: "A project named 'Website Redesign' already exists in this workspace."
Bad: "Duplicate error."
Good: "Could not load team members. Please try again."
Bad: "Error 500"
NO TECHNICAL DETAILS TO USERS
[ ] No error codes (SQLSTATE, HTTP status codes)
[ ] No stack traces
[ ] No variable names or internal identifiers
[ ] No "undefined", "null", "NaN" in user-facing messages
11. No Silent Failures
These are the most dangerous violations — the user thinks something worked when it didn't.
NEVER:
× console.log(error) without showing anything in the UI
× Catch an error and return undefined / null without showing a message
× Show a success toast after a failed operation
× Let a form submit without feedback (no spinner, no error, no success)
× Show "Saved" when the save actually failed
× Catch errors in a catch block with an empty body: catch (e) {}
× Swallow a network error and show stale data as if fresh
× Not handle the error state of a Promise or async/await call
ALWAYS:
✓ Every try/catch must show an error in the UI if the catch fires
✓ Every async call must have an error handler
✓ Every error handler must update UI state — not just log to console
✓ If you show a loading spinner, you must also handle the error that cancels it
Practice Task
→ Add/Edit Project Form Build a project form that correctly handles field errors, API errors (duplicate, forbidden), and network failures — with no silent failures.