Give users help, not confusion
TL;DR: Replace vague error messages with specific, actionable feedback that helps users solve problems.
Problems Addressed 😔
- User confusion and frustration
- No actionable guidance provided
- Technical jargon
- Poor Unhandled errors
- Poor UX
- Poor error recovery
- Incomplete Error Information
- Decreased user trust
- Generic messaging
- Silent Failures
Related Code Smells 💨

Code Smell 97 - Error Messages Without Empathy
Maxi Contieri ・ Oct 27 '21

Code Smell 166 - Low-Level Errors on User Interface
Maxi Contieri ・ Sep 28 '22

Code Smell 26 - Exceptions Polluting
Maxi Contieri ・ Nov 16 '20

Code Smell 132 - Exception Try Too Broad
Maxi Contieri ・ May 18 '22
Steps 👣
- Identify all generic error messages in your codebase that use terms like "Oops", "Something went wrong", or "An error occurred"
- Replace generic messages with specific descriptions of what happened
- Add actionable guidance telling users exactly what they can do to resolve the issue
- Implement proper internal logging to capture technical details for developers
- Add monitoring alerts to notify the development team when errors occur frequently
Sample Code 💻
Before 🚨
function processPayment(paymentData) {
try {
// Too broad try catch
validatePayment(paymentData);
chargeCard(paymentData);
sendConfirmation(paymentData.email);
} catch (error) {
// Generic error message shown to user
return {
success: false,
userMessage: "Oops! Something went wrong. Please try again.",
error: error.message
};
}
}
function handleError(res, error) {
// Exposing HTTP 500 to users
res.status(500).json({
message: "Internal Server Error",
error: error.message
});
}
After 👉
function processPayment(paymentData) {
try {
validatePayment(paymentData);
// This catch is specific to payment validation
} catch (error) {
// 1. Identify all generic error messages in your codebase
// that use terms like "Oops", "Something went wrong",
// or "An error occurred"
// 2. Replace generic messages
// with specific descriptions of what happened
// 3. Add actionable guidance telling users
// exactly what they can do to resolve the issue
// 4. Implement proper internal logging
// to capture technical details for developers
logger.error('Payment validation failed', {
userId: paymentData.userId,
error: error.message,
stack: error.stack,
timestamp: new Date().toISOString()
});
// 5. Add monitoring alerts to notify
// the development team when errors occur frequently
alerting.notifyError('PAYMENT_VALIDATION_FAILED', error);
if (error.code === 'INVALID_CARD') {
return {
success: false,
userMessage: "Your card information" +
" appears to be incorrect." +
"Please check your card number," +
" expiry date, and security code."
};
}
return {
success: false,
userMessage: "There was a problem validating" +
" your payment." +
"Please try again or contact support."
};
}
// You should break this long method
// Using extract method
try {
chargeCard(paymentData);
} catch (error) {
logger.error('Card charging failed', {
userId: paymentData.userId,
error: error.message,
stack: error.stack,
timestamp: new Date().toISOString()
});
alerting.notifyError('CARD_CHARGING_FAILED', error);
if (error.code === 'INSUFFICIENT_FUNDS') {
return {
success: false,
userMessage: "Your payment couldn't be processed"+
" due to insufficient funds. " +
"Please use a different payment method" +
" or contact your bank."
};
}
if (error.code === 'CARD_EXPIRED') {
return {
success: false,
userMessage: "Your card has expired. " +
"Please update your payment method with a current card."
};
}
return {
success: false,
userMessage: "There was a problem processing your payment." +
" Please try again or contact support."
};
}
try {
sendConfirmation(paymentData.email);
} catch (error) {
logger.error('Confirmation sending failed', {
userId: paymentData.userId,
error: error.message,
stack: error.stack,
timestamp: new Date().toISOString()
});
alerting.notifyError('CONFIRMATION_FAILED', error);
return {
success: true,
userMessage: "Payment processed successfully,"+
" but we couldn't send the confirmation email." +
" Please check your email address or contact support."
};
}
return { success: true,
userMessage: "Payment processed successfully." };
}
Type 📝
[X] Manual
Safety 🛡️
This refactoring changes the behavior and is safe if you keep logging and alerts active for debugging.
Avoid removing details needed by support teams.
The risk of breaking changes is low since you're improving existing error handling rather than changing core business logic.
Why is the Code Better? ✨
You give users useful guidance instead of confusion.
You create a better user experience by providing clear, actionable
feedback instead of confusing technical jargon.
Users understand what went wrong and know their next steps.
You separate concerns by keeping technical details in logs while showing business-friendly messages to
users.
Your support team gets better debugging information through structured logging.
You can proactively address system issues through monitoring alerts before users report them.
You keep technical information away from them, but still record it for faster issue resolution.
How Does it Improve the Bijection? 🗺️
You keep a closer match between the real world and your model. Instead of vague "Oops" messages, your system speaks in clear terms that reflect actual events.
Error messages in the real world contain specific information about what went wrong and how to fix it.
A cashier doesn't say "Oops, something went wrong" when your card is declined - they tell you the specific issue and suggest solutions.
This refactoring aligns the software model with Bijection error communication patterns, making the system more intuitive and helpful for users
Limitations ⚠️
You must be careful not to expose sensitive system information that could help attackers.
Some errors may need to remain generic for security reasons (like authentication failures).
Additionally, creating specific error messages requires more development time and thorough testing of error scenarios.
Refactor with AI 🤖
Suggested Prompt: 1. Identify all generic error messages in your codebase that use terms like "Oops", "Something went wrong", or "An error occurred" 2. Replace generic messages with specific descriptions of what happened 3. Add actionable guidance telling users exactly what they can do to resolve the issue 4. Implement proper internal logging to capture technical details for developers 5. Add monitoring alerts to notify the development team when errors occur frequently
Without Proper Instructions | With Specific Instructions |
---|---|
ChatGPT | ChatGPT |
Claude | Claude |
Perplexity | Perplexity |
Copilot | Copilot |
You | You |
Gemini | Gemini |
DeepSeek | DeepSeek |
Meta AI | Meta AI |
Grok | Grok |
Qwen | Qwen |
Tags 🏷️
- Exceptions
Level 🔋
[X] Intermediate
Related Refactorings 🔄
See also 📚
What's in a Good Error Message?
Error Handling: A Guide to Preventing Unexpected Crashes
Credits 🙏
Image by Ryan McGuire on Pixabay
This article is part of the Refactoring Series.
Top comments (2)
Really appreciate this deep dive into improving error handling! Clear, actionable messages are so underrated they’re a huge factor in user trust and support efficiency. The example refactor shows how breaking down broad try/catch blocks into specific handlers can really help both users and dev teams.
Also, love the connection to “bijection” matching software feedback precisely to real-world expectations is something we often overlook. Curious, how do you balance detailed error messages with security concerns around exposing too much info?
you expose all the info a user needs to understand the problem and log all the rest
No 'oops' hidding problems under the rug
Some comments may only be visible to logged-in visitors. Sign in to view all comments.