Skip to main content

Writing Effective Error Messages

Writing effective error messages is an essential skill in UX writing—it's an art. When something goes wrong, your error message can be the only thing standing between a user resolving the issue and quitting your product in frustration.

Here's a key question to ask about every error message: Does it lead users into a dead end? For example, if someone sees "Invalid or unsupported error," do they understand what caused the problem and what steps to take next? Or are they simply stuck?

The best error messages excel at two things:

  1. Clearly and simply explaining what happened.

  2. Clearly guiding users on how to fix the problem or who to contact for help.

Getting these elements right transforms frustrating moments into manageable challenges. Conversely, poor error messages can cause confusion, erode trust, and overwhelm your support team.

Ineffective error messages cost real money. Frustrated users may abandon their tasks, flood your support channels, or even switch to a competitor.

On the other hand, well-crafted error messages build trust, reduce support costs, keep users productive, and positively influence how they perceive your product—even when things go wrong.

This guide offers practical frameworks and real-world examples to help you create error messages that genuinely assist users in recovering quickly. Let’s get started.


The four pillars of effective error messages

1. Clarity: Explain what happened

Users can't fix problems they don't understand. Skip the jargon and tell them clearly what went wrong.

Try this framework: [Action] failed because [specific reason]

✓ Clear and Specific

Unable to save "Q4:Report.xlsx"

The file name contains invalid characters. File names can't include: / \ : * ? " < > |

✗ Vague and Unhelpful

Invalid file name



Why this works: The improved version tells users exactly which file failed, why it failed, and what characters caused the problem. No guessing required.


2. Context: Give them the details that matter

Include specific information that helps users understand what happened in their situation.

✓ Helpful Context

Can't upload "presentation.pptx"

File size: 47 MB
Maximum allowed: 25 MB

Compress the file or upgrade to a Pro account for 100 MB uploads.

✗ Missing Context

File too large





Why this works: Showing the actual size versus the limit helps users make decisions. Plus, the upgrade path turns a frustration into a potential sale. Win-win!


3. Actionability: Tell them what to do next

Never leave users hanging. Every error message needs clear next steps—no dead ends.

Try this framework: [Problem statement]. [Specific action to resolve]

✓ Clear Path Forward

Connection timeout

We couldn't reach the server at api.example.com.

  • Check your internet connection
  • Try again in a few moments
  • If this keeps happening, contact support with error code: NET_408

✗ Dead End

Network error occurred





Why this works: The improved version gives users a troubleshooting path and includes an error code for when they need to call support. They know exactly what to try and when to ask for help.


4. Empathy: Sound like a human

Your error messages should sound helpful, not robotic. And definitely not accusatory—nobody likes being blamed for things.

✓ Friendly and Helpful

We couldn't process your payment

Your card ending in 4242 was declined by your bank.

Check your card details or try a different payment method.

✗ Sounds Accusatory

Payment failed. You entered incorrect card information.



Why this works: The decline might not be about incorrect information—it could be low funds, fraud protection, or bank hiccups. The improved version doesn't make assumptions and treats users with respect.


Message structure template

Here's a simple structure that works for most error messages:

[SEVERITY INDICATOR - if it's critical]
[Clear problem statement]

[Why it happened - if that's helpful to know]
[Current state/impact - if relevant]

[Primary action they should take]
[Alternative actions - if you've got them]
[Support contact - if they need backup]

Here's how it looks in practice:

⚠️ Can't publish your changes

Your draft has 3 broken links that need fixing before you can publish:

  • Page 4: Link to "pricing" page not found
  • Page 7: External link to expired domain
  • Page 12: Anchor link "#contact" doesn't exist

Fix these links, then try publishing again. Need help? Check out our troubleshooting guide.


Error severity levels

Match your message's tone and urgency to how bad the error actually is:

Critical errors (everything's broken)

Impact: Nothing works, or data might be lost
Tone: Direct and urgent
Must include: What to do right now or who to contact

⛔ Service Unavailable

Our servers are down for emergency maintenance right now.

Don't worry—your work is saved. We expect to be back online by 3:00 PM EST.

Check our status: status.example.com Urgent issue? Call support at 1-800-HELP

High-priority errors (can't do important stuff)

Impact: Blocks key tasks people need to do
Tone: Clear and solution-focused
Must include: Specific steps to fix it

Can't generate report: Missing required data

Your Sales database hasn't synced since October 10, and reports need data from the last 7 days.

  • Ask your database admin to run a manual sync
  • Or schedule your report for after tonight's automatic sync (11 PM)

Medium-priority errors (annoying but manageable)

Impact: Inconvenient, but work can continue
Tone: Informative and supportive
Must include: How to work around it or try again

Preview failed to load

We couldn't generate a preview of "document.pdf," but your file uploaded successfully.

You can still share, download, or edit the file normally. Try refreshing to load the preview.

Low-Priority errors (heads up)

Impact: Barely a speed bump
Tone: Quick and light
Must include: Just acknowledge it happened

Some features unavailable offline

You can keep working, but changes won't sync until you're back online.


Real-World examples: Before and after

Here are some actual rewrites I did for a data encryption app. Let me walk you through what changed and why.

Example 1: Authentication error

OriginalImprovedWhat I Changed & Why
Error logging in. System cannot connect at this time.We're unable to sign you in

Your account has been deactivated. To reactivate your account, contact your administrator at admin@company.com or call ext. 5500.
The original message blamed a connection issue, but the real problem was account deactivation. The new version tells the truth, identifies who can help, and provides two ways to reach them. This eliminated a bunch of confused support calls.

Example 2: Permission denied

OriginalImprovedWhat I Changed & Why
Access denied to this resource. Please try again with an appropriate account.You don't have permission to view "Budget_2025.xlsx"

This file is restricted to Finance team members.

[Request Access] [View My Files]
The original was weirdly vague. The new version names the specific file, explains the restriction, and gives two clear options: ask for access or go back to your files. Security's still intact, but it's actually helpful now.

Example 3: Invalid Input Format

OriginalImprovedWhat I Changed & Why
Invalid/Unsupported file type. Please try again.Unsupported file format for directory sync

You entered: *.exe
Allowed formats:
. (all file types)
*.{extension}(specific types)

Examples: *.pdf, *.docx, *.xlsx
The original just said "wrong format" and left people guessing. The new version shows what they typed, explains the correct format structure, and gives real examples. Now users can see exactly what to fix.

Example 4: Database connection error

OriginalImprovedWhat I Changed & Why
ERR_DB_CONN_REFUSED: Exception at line 142Can't load customer data

We're unable to connect to the customer database. Your recent work is saved locally.

This usually fixes itself in a few minutes. Try refreshing the page.

Still broken after 10 minutes? Contact IT support with error code: DB_503
The original was pure developer-speak. The new version explains the impact (can't load data), reassures them (work is saved), suggests a fix (refresh), and includes a support code. Users get what they need, and IT still gets the technical details for debugging.

Technical implementation best practices

Keep user messages and logs separate

Never show technical stack traces to users. Log all the geeky details separately for debugging.

// DON'T DO THIS
catch (error) {
showError(error.message); // Might show scary technical stuff
}

// DO THIS INSTEAD
catch (error) {
// Log all the technical details
logger.error('Document save failed', {
error: error.stack,
userId: currentUser.id,
documentId: doc.id,
timestamp: Date.now()
});

// Show something friendly to users
showError({
title: 'Unable to save document',
message: 'Please try again. If this keeps happening, contact support with code: DOC_500',
code: 'DOC_500',
actions: ['retry', 'contact_support']
});
}

Use progressive disclosure for details

Show the essential info first. Let users dig deeper if they want the technical stuff.

<ErrorMessage>
<Title>Payment processing failed</Title>
<Message>
We couldn't process your payment. Please verify your payment
information and try again.
</Message>

<ExpandableDetails>
<Summary>Technical details</Summary>
<Details>
Transaction ID: txn_1234567890<br />
Error code: CARD_DECLINED<br />
Provider response: Insufficient funds<br />
Timestamp: 2025-10-16 14:23:45 UTC
</Details>
</ExpandableDetails>

<Actions>
<Button primary>Update Payment Method</Button>
<Button secondary>Contact Support</Button>
</Actions>
</ErrorMessage>

Security considerations

Sometimes you need to be intentionally vague to protect security. Here's where to draw the line.

Authentication errors

DO keep it ambiguous

Incorrect username or password

Try again, or click "Forgot password" to reset your password.

DON'T tell them which part failed

Username not found
✗ Password incorrect for user@example.com

Why this matters: Specific messages help attackers figure out valid usernames. That's literally one of their first steps in breaking into accounts.


Password creation errors

During password creation (totally fine to be specific):

✓ Password must contain:
✗ At least 8 characters (current: 6)
✓ One uppercase letter
✗ One number
✓ One special character (!@#$%^&*)

During sign-in (keep it vague):

✓ Password doesn't meet security requirements.

Forgot your password? Click "Reset password" below.

Why the difference: Real-time feedback during creation helps people succeed. But at sign-in, you don't want to help attackers learn your password rules to crack accounts.


System information disclosure

Never expose internal system details that could help attackers.

DO use friendly fallbacks

Unable to load account information

We're having some technical difficulties. Please try again in a few moments or contact support if this continues.

Error code: DB_500

DON'T expose your infrastructure

MySQL error: Table 'prod_users.accounts' doesn't exist

Can't connect to internal server prod-db-01.internal.company.com:3306

Stack trace: at DatabaseController.fetchUser (/var/www/app/controllers/db.js:247)

Why this matters: Revealing database names, server addresses, or stack traces gives attackers a roadmap to exploit your system. Always keep the technical details in your logs, not your UI.


Common mistakes to avoid

1. Using technical jargon

Correct

Can't load your profile. Refresh the page or try again later.

Unable to connect to the server. Check your internet connection and try again.

Something went wrong. Try again. If this keeps happening, contact support.

Incorrect

NullReferenceException in UserController

HTTP 500 Internal Server Error

Segmentation fault (core dumped)

Why this matters: Technical terms confuse users and make them feel alienated. Always write for the least technical person who might see the error.


2. Blaming the user

Correct

Enter a valid email address (example@domain.com)

Incorrect username or password. Try again or reset your password.

Add a subject line to send your message

Incorrect

You entered invalid data

Your password is wrong

You must include a subject line

Why this matters: Blaming users makes them defensive and frustrated. Always take responsibility and offer help.


3. Unhelpful confirmations

Correct

Delete "Project_Final.doc"? This can't be undone. [Cancel] [Delete]

Can't save changes. [Try Again] [Save Copy] [Cancel]

Connection lost. Reconnecting... [Manual Retry] [Work Offline]

Incorrect

Are you sure? Yes/No

Operation failed. OK

Error occurred. Dismiss

Why this matters: Blaming users makes them defensive and frustrated. Always take responsibility and offer help.


4. Confusing success with failure

Correct

Changes saved successfully

Import complete: 1,247 records added

System check passed: All services running normally

Incorrect

Error: Operation completed successfully

Failed to succeed

Warning: No problems found

Why this matters: Users need to instantly recognize if something went wrong or right. Mixing success and failure cues leads to confusion and mistakes.


Testing your error messages

1. Can people actually understand them?

Test your messages with people who didn't write them. Ask:

  • "What happened here?"

  • "What would you do next?"

  • "Do you have enough info to fix this?"

If they're confused or guessing, your message needs work.


2. Do they work in context?

Test your errors in realistic situations where they'll actually appear. Check these things:

  • Does it show up at the right moment?

  • Does it block important information users need?

  • Can users dismiss it when they should be able to?

  • Does it break your page layout?

  • Does it work on mobile devices and tablets?

  • Is all the text visible, or does it get cut off?

  • Does it stay visible until the problem is actually fixed?

  • If multiple errors happen, do they stack nicely or turn into a mess?

If your error looks fine in isolation but terrible in the actual product, it needs refinement.


3. Are they accessible?

Make sure everyone can understand and interact with your errors, regardless of how they access your product. Test these aspects:

  • Does it have the proper ARIA role so assistive tech recognizes it?

  • Do screen readers announce it clearly?

  • Is the color contrast strong enough (minimum 4.5:1)?

  • Does it use more than just color to convey it's an error?

  • Can keyboard-only users navigate to and through it?

  • Does focus move to the error if it's critical?

  • Is the text readable when someone zooms to 200%?

  • Are buttons and links large enough to tap easily (at least 44×44px)?

If users with disabilities can't understand or act on your error, you're leaving people behind.


4. Did you test the weird scenarios?

Edge cases happen more often than you think. Try these situations that will definitely occur in production:

  • Really long file names—does your truncation work smoothly?

  • Special characters in dynamic content—does everything still display correctly?

  • Multiple simultaneous errors—do they pile up gracefully?

  • Slow internet connections—does the error still appear and make sense?

  • Different languages—does it work if you support internationalization?

  • JavaScript disabled—can users still understand what happened?

  • Old or slow devices—does it render without breaking?

  • Repeated errors—does showing the same error multiple times get annoying?

If you haven't tested these scenarios, someone will find the bug for you—and they won't be happy about it.


Sample details

Project: Work-related, SaaS data encryption app, MVP Launch
My Role: Sr. Technical Writer, UX Writer
Tools: Figma, Microsoft Excel

The examples below show the original error messages as they appeared in the application before the rewrite.


The bottom line

Here's what I've learned writing hundreds of error messages:

Error messages are a feature, not an afterthought. They directly affect whether people like your product and how much your support team has to handle.

Every error needs four things: what happened, why it matters, what to do about it, and how to get help if needed.

Write for humans, log for developers. Never show users technical gobbledygook, but always capture it in your logs.

Test with real people. What makes perfect sense to you might be total gibberish to someone seeing the error for the first time.

Security and helpfulness can coexist. Be as helpful as possible without compromising your system's security.

The best error messages turn a frustrating moment into a chance to build trust with your users. And honestly? That's worth the effort.