Error Messages

How to write thoughtful error messaging to increase successful interactions.

Principles

Prevent the error before writing one

The best approach to errors is preventing them from happening. Before you write a message, evaluate if the possibility of error can be avoided altogether.


You can often prevent errors by:

  • Using helper text to set expectations about the input
  • Choosing a form element that guides correct input (e.g. Time Picker to choose a time)
  • Using inline validation to flag issues as they happen
  • Displaying inline validation over a page-level error when only one field is affected

You can also consider design and engineering solutions that support recovering silently from potential errors. Ask yourself: how can we automatically guide correct input without leveraging errors? For example, this might mean trimming content in a form field to the expected format rather than displaying an error.

Write the message before choosing the component

It can be tempting to choose the messaging component before authoring the message. Draft the message first, free of UI constraints, then choose a solution that fits.


Match the component choice to the severity and complexity of the message:

Component

Use for

Helper text

Form field level guidance on what to enter and in what format.

Inline Validation

Feedback about issues connected to a single field, as they happen (often in real time, on the client side).

Error Summary

Feedback about issues connected to multiple fields that must be resolved before continuing.

Callout

System-level messages that aren’t tied to a single action (connectivity, service status).

Dialog

High-stakes, blocking errors the user must acknowledge before continuing.

Snackbar

Brief, low-stakes feedback tied to a user action (e.g. "Space saved").

Be specific

Generic messages are the least useful. Write a distinct message for each case whenever possible. When pointing users at a specific piece of information to address, use real values, like numbers, dates, limits, file names, or IDs.

Do

Rename deployment-config-prod.yaml to 250 characters or less.
The release 2024.3.1 already exists in the Production environment.
Your deployment to web-app-prod timed out after 30 minutes.

Don't

This filename is too long.
This release already exists.
Deployment failed.

Always check for “unknown” reasons for errors, as most of them should have a knowable cause. As a last resort, be honest: "Something isn't working on our end. Try again in a few minutes."

Be helpful

When displaying errors, we have an opportunity to build user confidence and use positive framing. If we’re clear about what happened and what steps to follow, people feel empowered to resolve issues by themselves, rather than having to contact customer support.


If we focus on what can be done to resolve, we create positive reinforcement, instead of showcasing lack of reliability, or being judgmental about people’s ability to navigate the product successfully.

Don’t blame the user

Even when the user caused the error, focus on the problem and how to fix, not the mistake. Avoid being judgmental and assigning blame, as it results in a negative user experience in an already frustrating context.

Do

Your computer appears to be offline.
Your session ended. Sign in again to keep working.

Don't

You went offline.
You didn't stay signed in.

Be careful with error codes

Only include an error code when the user can act on it. For example, when they’ll quote it to customer support, search for it in our docs, or look it up in a log. Append error codes at the end of the message (in brackets) so they provide the context, and don’t use them at the beginning of the sentence.

Do

We couldn't reach the deployment target. Check that the target is online, then try again. (Error 206)
We couldn’t reach /api/deployments/Deployments-1234 (Error 500)

Don't

Error 206: target unreachable
The Octopus Server returned 500 Internal Server Error from /api/deployments/Deployments-1234.

If an error code exists only for our own debugging, omit it from the user-facing message.


Anatomy

Comprehensive error messages have three distinct parts to guide users:

  • What happened: the outcome of an error
  • The cause (optional): detailed explanation of why the error occurred (only include if it helps to resolve the error)
  • How to fix it: actionable step to take to resolve the error

What happened

This is the first part of the message, often in heading format (if the selected component supports this). Communicate the high-level outcome of an error in plain language, focusing on the impact to the user.


Try keeping headings to one sentence. Headings have no full stop at the end of the sentence.

Do

Your variables couldn't be saved

Don't

Operation failed: VariableEdit returned 403

The cause

Second part of the message is the underlying cause of the error, and it’s optional. Only include it when it helps the user understand what to do. If explaining the cause adds noise without adding clarity, leave it out.


Complete sentences in this section have a full stop.

Do

You don’t have permission to edit unscoped variables.

Don't

Missing permission: VariableEditUnscoped.

How to fix it

In the last part, offer clear and actionable advice on how to remedy the issue. If possible, it should be a one step or one click fix (e.g. clicking “Try again”).


If escalation is the only option, give the user concrete actions: the specific permission level to request, the person to contact, and the documentation to refer to. When referring to help documentation, link to sections explaining the error, not generic pages or the home page.


If there’s one way to resolve the error successfully, consider replacing the what happened heading with the instruction. This approach allows users to resolve common issues more quickly without having to scan lengthy instructions. Complete sentences in this section have a full stop.

Do

Contact your Octopus administrator to request the VariableEditUnscoped permission.

Don't

Contact your administrator.

Handling multiple errors

When several form fields have errors at once, we aggregate them into a single message rather than displaying separate messages (multiple error panels across a form).


Displaying an Error Summary at the top of a form helps quickly navigate and address problem areas.

Do

To create this release, make 2 changes:

- Add a release version
- Select a channel

Don't

Invalid release version. Invalid channel.


Voice and tone

Use plain language

Use plain English. Avoid internal language, uncommon acronyms, and jargon.

Do

We couldn’t connect to your deployment target.

Don't

TentacleCommunicationException encountered during pre-deployment.

Use active voice

We use active voice, as it’s quicker to parse and more direct. There might be cases in error messaging where deliberate use of passive voice helps more thoughtful delivery. When the user caused the error, passive voice can soften a message that would otherwise sound accusatory.

Do

Your changes couldn't be saved.

Don't

You didn't save your changes.

Use "we" only when owning mistakes

We refer to ourselves (“we”) only when Octopus genuinely caused the underlying problem. Use this approach when it’s important to highlight whose responsibility it is to take action to resolve.

Do

When it's Octopus's responsibility:
We couldn't generate your report. Try again in a few minutes.

Do

When it's user's responsibility:
Your deployment target is offline. Check the target and try again.

Match tone to severity

Errors range from mild inconvenience to genuine harm. We always match the tone to the impact to the user. As severity rises, humor drops out completely. There’s no room for a playful tone in a serious error, as it reads as dismissive and out of touch.

Severity

Description

Example

Minor

The user can fix the error themselves, quickly, with no real consequence.

For example: a wrong password, a dropped connection, a step that needs renaming before it can be saved.

Your password didn't match. Try again.

Moderate

The user can fix the error, but it takes effort, another person, or another tool.

For example: a missing permission, a sync issue, a stuck deployment that needs canceling.

Your role doesn't have permission to deploy to Production. Ask your Octopus administrator to grant you the DeploymentCreate permission for this environment.

Severe

The user can’t fix it themselves, and the consequences are real: data loss, financial impact, and security implications.

For example: a corrupted backup, a failed billing event, a Runbook that didn't run when it should have.

We couldn't process your subscription renewal. Contact support@octopus.com so we can look into it with you. Your instance will keep running while we sort this out.

Words to avoid

The words below add stress without adding meaning. When authoring error messaging, consider their replacements:

Word

Reason to avoid

What to use instead

Please

Adds length without meaning

Don’t use.

Sorry

Sounds insincere for minor issues

Reserve only for serious errors (data loss, major user action needed, genuine Octopus faults).

Invalid

User-hostile and vague

Be specific in the description of what went wrong.

Failed, failure

Catastrophizing

"Couldn't", "didn't", or describe the outcome of the error.

Wrong, incorrect

Blames the user

Describe the expected input.

Forbidden, denied, suspended, blocked

Hostile

"You don't have permission to…"

Oops, whoops, hmm, yikes

Makes light of the user’s frustration

Describe the situation in plain language.

Error

States the obvious

Lead with what happened instead.