Error Messages
Error messages are critical touchpoints. A well-written error message turns a frustrating experience into a recoverable one. In the Mukoko ecosystem, where users may have limited connectivity and varying technical literacy, clear error communication is essential.
Structure
Every error message should answer three questions:
- What happened — describe the problem simply
- Why it happened — give context if it helps
- What to do next — provide a clear action
✓ "Could not save your changes. The connection was lost. Check your internet and try again."
✗ "Error 500: Internal Server Error"Tone
- Calm — do not alarm the user; errors are normal
- Helpful — focus on the solution, not the blame
- Honest — if you do not know why, say so
- Brief — keep it under two sentences when possible
Do not blame the user
✓ "That password is too short. Use at least 8 characters."
✗ "You entered an invalid password."
✓ "We could not find that page."
✗ "You requested a page that does not exist."Do not use technical jargon
✓ "Something went wrong. Please try again."
✗ "Unhandled exception in middleware pipeline."
✓ "Could not connect to the server."
✗ "ECONNREFUSED: Connection refused at 127.0.0.1:3000"Patterns by type
Validation errors
Show inline, next to the field that needs attention:
Field: Email address
Error: "Enter a valid email address"
Field: Password
Error: "Password must be at least 8 characters"
Field: Phone number
Error: "Enter a phone number with country code (e.g. +263 77 123 4567)"Use the FormMessage component from the form system for consistent styling.
Network errors
"Could not connect. Check your internet connection and try again."
"The request timed out. This usually means a slow connection. Try again in a moment."
"You appear to be offline. Your changes will be saved when you reconnect."Permission errors
"You do not have access to this page. Contact your administrator."
"Your session has expired. Sign in again to continue."Not found errors
"We could not find that page. Check the URL or go back to the home page."
"No results found for 'search term'. Try a different search."Server errors
"Something went wrong on our end. We are looking into it. Try again in a few minutes."
"This feature is temporarily unavailable. Please try again later."Implementation
Form validation
Use react-hook-form with zod for consistent validation messaging:
const schema = z.object({
email: z.string().email("Enter a valid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
})Toast notifications
Use the sonner toast for non-blocking error feedback:
import { toast } from "sonner"
toast.error("Could not save changes", {
description: "Check your connection and try again.",
})Error boundaries
For component-level crashes, the error boundary displays a recovery UI:
<SectionErrorBoundary fallback={<p>This section could not load. Try refreshing.</p>}>
<MyComponent />
</SectionErrorBoundary>Examples
Good error messages
| Situation | Message |
|---|---|
| Wrong password | ”Incorrect password. Try again or reset your password.” |
| File too large | ”This file is too large. Maximum size is 10 MB.” |
| Rate limited | ”Too many attempts. Wait a moment and try again.” |
| Offline | ”You are offline. Changes will sync when you reconnect.” |
| Feature flag off | ”This feature is not yet available in your region.” |
Bad error messages
| Message | Problem |
|---|---|
| ”Error” | No context, no action |
| ”Invalid input” | What input? What is wrong with it? |
| ”Something went wrong” (alone) | No next step |
| ”Null pointer exception” | Technical jargon |
| ”Please contact support” | Lazy — give a self-service option first |
Last updated on