Writing Effective Error Messages

Last updated: 10/16/2025

When something goes wrong, your error message can be the only thing standing between a user resolving the issue and abandoning your product. A key question to ask about every error message: does it lead users to a dead end?

For example, if someone sees "Invalid or unsupported error," do they understand what caused the problem and what to do next? Or are they stuck?

Effective error messages do two things well:

  1. Explain clearly and simply what happened.
  2. Guide users on how to fix the problem or who to contact for help.

Poor error messages cause confusion, erode trust, and overwhelm your support team. Well-crafted error messages build trust, reduce support costs, and keep users productive — even when things go wrong.

The four pillars of effective error messages

1. Clarity: explain what happened

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

Framework: [Action] failed because [specific reason]

✓ Clear and specific

Unable to save "Q4

.xlsx"

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

✗ Vague and unhelpful

Invalid file name



The improved version tells users exactly which file failed, why it failed, and what characters caused the problem.

2. Context: give users 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





Showing the actual size versus the limit helps users make decisions. The upgrade path also turns a frustration into an actionable next step.

3. Actionability: tell users what to do next

Every error message needs clear next steps. Never leave users without a path forward.

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





The improved version gives users a troubleshooting path and an error code for when they contact support.

4. Empathy: write like a human

Error messages should sound helpful, not robotic. Avoid accusatory language — users rarely cause errors intentionally.

✓ Helpful and neutral

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.

✗ Accusatory

Payment failed. You entered incorrect card information.



A card decline might result from low funds, fraud protection, or a bank hold — not necessarily incorrect input. The improved version avoids assumptions and treats users with respect.


Message structure template

Use this structure for most error messages:

[SEVERITY INDICATOR - if critical]
[Clear problem statement]

[Why it happened - if useful]
[Current state/impact - if relevant]

[Primary action to take]
[Alternative actions - if available]
[Support contact - if needed]

Example:

⚠️ 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 the troubleshooting guide.


Error severity levels

Match your message's tone and urgency to the severity of the error.

Critical errors

Impact: Nothing works, or data might be lost
Tone: Direct and urgent
Must include: Immediate action or contact information

⛔ Service unavailable

Our servers are down for emergency maintenance.

Your work is saved. Estimated recovery time: 3
PM EST.

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

High-priority errors

Impact: Blocks key tasks
Tone: Clear and solution-focused
Must include: Specific steps to resolve the issue

Can't generate report: missing required data

Your Sales database hasn't synced since October 10. Reports require data from the last 7 days.

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

Medium-priority errors

Impact: Inconvenient, but work can continue
Tone: Informative and supportive
Must include: A workaround or retry option

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. Try refreshing to load the preview.

Low-priority errors

Impact: Minor disruption
Tone: Brief and light
Must include: Acknowledgment of the issue

Some features unavailable offline

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


Real-world examples: before and after

The following examples show error message rewrites for a SaaS data encryption application.

Example 1: Authentication error

OriginalImprovedWhat changed and 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 blamed a connection issue when the real problem was account deactivation. The improved version identifies the cause, names who can help, and provides two contact options.

Example 2: Permission denied

OriginalImprovedWhat changed and why
Access denied to this resource. 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 gave no useful information. The improved version names the specific file, explains the restriction, and gives two clear options.

Example 3: Invalid input format

OriginalImprovedWhat changed and why
Invalid/Unsupported file type. 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 identified no specific problem. The improved version shows what was entered, explains the correct format, and provides examples.

Example 4: Database connection error

OriginalImprovedWhat changed and 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 issue usually resolves in a few minutes. Try refreshing the page.

Still unavailable after 10 minutes? Contact IT support with error code: DB_503
The original exposed a raw technical error. The improved version explains the impact, reassures users their work is saved, suggests a fix, and includes a support code.

Technical implementation best practices

Keep user messages and logs separate

Never expose technical stack traces to users. Log all technical details separately for debugging.

// Avoid this pattern
catch (error) {
    showError(error.message); // May expose technical details
}

// Use this pattern instead
catch (error) {
    // Log technical details for debugging
    logger.error('Document save failed', {
        error: error.stack,
        userId: currentUser.id,
        documentId: doc.id,
        timestamp: Date.now()
    });

    // Show a clear message to users
    showError({
        title: 'Unable to save document',
        message: '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 essential information first. Let users expand technical details if needed.

<ErrorMessage>
    <Title>Payment processing failed</Title>
    <Message>
        We couldn't process your payment. 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

Some situations require intentionally vague messages to protect security.

Authentication errors

DO: keep it ambiguous

Incorrect username or password

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

DON'T: identify which part failed

Username not found

✗ Password incorrect for user@example.com

Specific messages help attackers identify valid usernames — a common first step in account compromise.

Password creation errors

During password creation, 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? Select "Reset password" below.

Real-time feedback during password creation helps users succeed. At sign-in, specific feedback about password rules can help attackers exploit your system.

System information disclosure

Never expose internal system details to users.

DO: use a friendly fallback

Unable to load account information

We're having technical difficulties. Try again in a few moments. If this continues, contact support.

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

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

)

Database names, server addresses, and stack traces give attackers a roadmap to exploit your system. Keep 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)

Technical terms alienate users. Write for the least technical person who might encounter 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

Accusatory messages make users defensive. Take responsibility for the experience and offer a clear path forward.

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

Vague confirmations leave users without a path forward. Clear labels and specific actions reduce confusion and support requests.

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

Users need to recognize immediately whether something succeeded or failed. Mixing success and failure cues leads to confusion and mistakes.


Testing your error messages

1. Comprehension

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

  • "What happened here?"
  • "What would you do next?"
  • "Do you have enough information to fix this?"

If they're confused or guessing, the message needs revision.

2. Context

Test your errors in realistic situations. Verify:

  • Does it appear at the right moment?
  • Does it block information users need?
  • Can users dismiss it when appropriate?
  • Does it break the page layout?
  • Does it work on mobile and tablet?
  • Is all text visible, or does it get cut off?
  • Does it stay visible until the problem is resolved?
  • Do multiple simultaneous errors display cleanly?

An error that looks fine in isolation might behave differently in the product. Test in context.

3. Accessibility

Ensure all users can understand and interact with your errors. Verify:

  • Does it carry the correct ARIA role so assistive technology recognizes it?
  • Do screen readers announce it clearly?
  • Does color contrast meet the minimum ratio (4.5
    )?
  • Does it use more than color alone to indicate an error?
  • Can keyboard-only users navigate to and through it?
  • Does focus move to the error when it's critical?
  • Is the text readable at 200% zoom?
  • Are buttons and links large enough to tap (minimum 44×44 px)?

4. Edge cases

Test scenarios that commonly occur in production:

  • Long file names — does truncation display correctly?
  • Special characters in dynamic content — does everything render correctly?
  • Multiple simultaneous errors — do they stack cleanly?
  • Slow connections — does the error appear and remain readable?
  • Internationalization — does the message work in supported languages?
  • JavaScript disabled — can users still understand what happened?
  • Low-performance devices — does the error render without breaking?
  • Repeated errors — does the same error appearing multiple times degrade the experience?

Reference examples

The following examples show the original error messages from a SaaS data encryption application before revision.


Key principles

Error messages are a feature, not an afterthought. They directly affect user trust and support volume.

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

Write for users, log for developers. Never expose technical output in the UI, but always capture it in your logs.

Test with real people. A message that seems obvious to its author might be unclear to a first-time user.

Security and helpfulness can coexist. Be as helpful as possible without exposing system details that create risk.