Generic error messages:
- Don't help users - "Error occurred" - what error?
- Don't help developers - No debugging information
- Frustrate everyone - No actionable guidance
- Waste time - Must reproduce to debug
// Useless
wp_die('Error occurred');
// No context
return 'Update failed';
// Technical jargon
throw new Exception('ValueError: parameter out of range');// Specific and actionable
return new WP_Error(
'email_already_exists',
sprintf(
'Email "%s" is already registered. <a href="%s">Log in</a>?',
$email,
wp_login_url()
),
['email' => $email]
);- Be Specific - Say what failed
- Add Context - Include relevant values
- Be Actionable - Tell user what to do
- Use Error Codes - For programmatic handling
- Separate User/Developer Messages - User-friendly + detailed logs
- Security Exception - Use generic messages for authentication failures
- ✅ "Email address is already registered. Log in?"
- ✅ "Please enter your username" (empty field validation)
- ✅ "Invalid username or password" (authentication - generic for security)
- ❌ "Validation error"
- ❌ "No account found for username 'john'" (reveals if username exists)
- ❌ "Password is incorrect" (confirms username exists)
- ✅ "Failed to update user meta for user ID 123, key 'profile_data'"
- ❌ "Update failed"
Authentication errors should be generic to prevent user enumeration attacks:
- ✅ GOOD: "Invalid username or password" (don't reveal which is wrong)
- ❌ BAD: "No account found" (reveals username doesn't exist)
- ❌ BAD: "Password is incorrect" (confirms username exists)
However, input validation can be specific:
- ✅ "Please enter your username" (empty field)
- ✅ "Please enter your password" (empty field)
✅ Explain what happened
✅ Why it happened
✅ What user should do
✅ Include context for debugging
✅ Use error codes for handling
❌ Don't use generic "Error"
❌ Don't use error numbers without explanation
❌ Don't show technical details to users
❌ Don't lose original error information