- Write-Error
- Syntax
- Description
- Examples
- Example 1: Write an error for RegistryKey object
- Example 2: Write an error message to the console
- Example 3: Write an error to the console and specify the category
- Example 4: Write an error using an Exception object
- Parameters
- -Category
- -CategoryActivity
- -CategoryReason
- -CategoryTargetName
- -CategoryTargetType
- -ErrorId
- -ErrorRecord
- -Exception
- -Message
- -RecommendedAction
- -TargetObject
- Inputs
- Outputs
- Error recording — How to record errors in your application to debug later
- How to manually record errors
- What information to record
- Final notes
- Credits
- How to Write Helpful Error Messages to Improve Your App’s User Experience
- The current state of error messaging
- Why should I create sane error messaging?
- To help maintain developer sanity
- To help maintain organisation sanity
- To help maintain end-user sanity
- What makes a good error message?
- How can I start writing sane error messages?
- How to set up your error messages
- How to consume your error messages
- Conclusion
- Why can’t the server-side just return these messages?
- Will I need to create an instance of error-messages for every API consumer?
- I think this package should have X or do Y differently
- Further Reading
Write-Error
Writes an object to the error stream.
Syntax
Description
The Write-Error cmdlet declares a non-terminating error. By default, errors are sent in the error stream to the host program to be displayed, along with output.
To write a non-terminating error, enter an error message string, an ErrorRecord object, or an Exception object. Use the other parameters of Write-Error to populate the error record.
Non-terminating errors write an error to the error stream, but they do not stop command processing. If a non-terminating error is declared on one item in a collection of input items, the command continues to process the other items in the collection.
To declare a terminating error, use the Throw keyword. For more information, see about_Throw.
Examples
Example 1: Write an error for RegistryKey object
This command declares a non-terminating error when the Get-ChildItem cmdlet returns a Microsoft.Win32.RegistryKey object, such as the objects in the HKLM: or HKCU: drives of the PowerShell Registry provider.
Example 2: Write an error message to the console
This command declares a non-terminating error and writes an «Access denied» error. The command uses the Message parameter to specify the message, but omits the optional Message parameter name.
Example 3: Write an error to the console and specify the category
This command declares a non-terminating error and specifies an error category.
Example 4: Write an error using an Exception object
This command uses an Exception object to declare a non-terminating error.
The first command uses a hash table to create the System.Exception object. It saves the exception object in the $E variable. You can use a hash table to create any object of a type that has a null constructor.
The second command uses the Write-Error cmdlet to declare a non-terminating error. The value of the Exception parameter is the Exception object in the $E variable.
Parameters
-Category
Specifies the category of the error. The default value is NotSpecified. The acceptable values for this parameter are:
- NotSpecified
- OpenError
- CloseError
- DeviceError
- DeadlockDetected
- InvalidArgument
- InvalidData
- InvalidOperation
- InvalidResult
- InvalidType
- MetadataError
- NotImplemented
- NotInstalled
- ObjectNotFound
- OperationStopped
- OperationTimeout
- SyntaxError
- ParserError
- PermissionDenied
- ResourceBusy
- ResourceExists
- ResourceUnavailable
- ReadError
- WriteError
- FromStdErr
- SecurityError
- ProtocolError
- ConnectionError
- AuthenticationError
- LimitsExceeded
- QuotaExceeded
- NotEnabled
For information about the error categories, see ErrorCategory Enumeration.
Type: | ErrorCategory |
Accepted values: | NotSpecified, OpenError, CloseError, DeviceError, DeadlockDetected, InvalidArgument, InvalidData, InvalidOperation, InvalidResult, InvalidType, MetadataError, NotImplemented, NotInstalled, ObjectNotFound, OperationStopped, OperationTimeout, SyntaxError, ParserError, PermissionDenied, ResourceBusy, ResourceExists, ResourceUnavailable, ReadError, WriteError, FromStdErr, SecurityError, ProtocolError, ConnectionError, AuthenticationError, LimitsExceeded, QuotaExceeded, NotEnabled |
Position: | Named |
Default value: | NotSpecified |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-CategoryActivity
Specifies the action that caused the error.
Type: | String |
Aliases: | Activity |
Position: | Named |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-CategoryReason
Specifies how or why the activity caused the error.
Type: | String |
Aliases: | Reason |
Position: | Named |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-CategoryTargetName
Specifies the name of the object that was being processed when the error occurred.
Type: | String |
Aliases: | TargetName |
Position: | Named |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-CategoryTargetType
Specifies the type of the object that was being processed when the error occurred.
Type: | String |
Aliases: | TargetType |
Position: | Named |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-ErrorId
Specifies an ID string to identify the error. The string should be unique to the error.
Type: | String |
Position: | Named |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-ErrorRecord
Specifies an error record object that represents the error. Use the properties of the object to describe the error.
To create an error record object, use the New-Object cmdlet or get an error record object from the array in the $Error automatic variable.
Type: | ErrorRecord |
Position: | |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-Exception
Specifies an exception object that represents the error. Use the properties of the object to describe the error.
To create an exception object, use a hash table or use the New-Object cmdlet.
Type: | Exception |
Position: | |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-Message
Specifies the message text of the error. If the text includes spaces or special characters, enclose it in quotation marks. You can also pipe a message string to Write-Error .
Type: | String |
Aliases: | Msg |
Position: | |
Default value: | None |
Accept pipeline input: | True |
Accept wildcard characters: | False |
-RecommendedAction
Specifies the action that the user should take to resolve or prevent the error.
Type: | String |
Position: | Named |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
-TargetObject
Specifies the object that was being processed when the error occurred. Enter the object, a variable that contains the object, or a command that gets the object.
Type: | Object |
Position: | Named |
Default value: | None |
Accept pipeline input: | False |
Accept wildcard characters: | False |
Inputs
You can pipe a string that contains an error message to this cmdlet.
Outputs
None
This cmdlet returns no output. It only writes to the errpr message stream.
Error recording — How to record errors in your application to debug later
Recording errors is an important part of error handling. In short, when certain errors occur in programs, you want to know about it. This is particularly important with bugs.
- know that they occurred
- have useful information about them so you can debug them later
One way to do this is to use an error monitoring or logging service. Some examples are New Relic and Splunk. These will automatically record any program errors and such.
In particular, logging is very useful. It records a lot of information about what’s happening in your program. This can help a lot with debugging.
Alternatively, you can manually record information about errors.
How to manually record errors
The goal is to be able to view errors later. You can achieve that in any number of ways.
One way is to manually record errors in a database.
To do this, you can:
- prepare your database for recording errors
- set up some code to record errors to the database
- set up a global error handler to catch errors. (This error handler would call the code from step 2)
- set up an endpoint in the back end so the front end can record errors too. (This endpoint would call the code from step 2)
For example, you might use a MongoDB database with a collection for errors. Every time an error occurs in your application, add information about it to the collection. You can organise the information in any way you like. For example, you could organise by the type of error or exception, by the error message, or by the last code in the call stack for the error.
After setting that up, you could set up a global error handler. This error handler would be called on errors that occur in your application. In the handler, record the error in your database.
Different frameworks and «environments» provide different ways to set up global error handlers. For example, in the Unity game engine, you can use Application.logMessageReceived += Handler; . On the front end of a website, you can use window.addEventListener(‘error’, handler); .
Finally, you can set up an endpoint so that the front end can record errors too. Then, the front end can make a network request with information about the error it encountered.
Here’s an example call you could make from the front end:
Exit fullscreen mode
The function handleError above is executed any time an error occurs. It creates an object with useful information about the error. Then, it sends a network request to the back end. The back end will then record the information about the error so it can be viewed later.
What information to record
You want as much useful information about the error as possible. This will help you debug it later.
The article .NET best practices on exceptions has some guidelines for this. Adapted for both error values and exceptions, they are to:
- use the predefined error types in your programming language if they’re relevant. Only create custom types if the predefined ones don’t apply.
- if you create custom error types:
- they should usually be subclasses of the main error types (if you use an OOP language)
- they can optionally have custom properties (if they would be useful)
- use grammatically correct error messages. For example ‘The file «foo.txt» could not be found.’.
- include a localised string message in every error (if your application is localised)
Final notes
So that’s it for this article. I hope that you found it useful.
As always, if any points were missed, or if you disagree with anything, or have any comments or feedback then please leave a comment below.
For the next steps, I recommend looking at the other articles in the error handling series.
Alright, thanks and see you next time.
Credits
Recording photo — Photo by Krists Luhaers on Unsplash
How to Write Helpful Error Messages to Improve Your App’s User Experience
Gone are the days of useless and generic error messaging.
Screenshot taken moments before a rage-quit
If you’re here, you’re likely concerned with making your user-facing products as delightful as possible. And error messaging plays an important role in that.
Having useful error messages can go a long way toward making a frustrating scenario for an end-user as pleasant as possible.
This article is split into two parts. The first builds context around error messages and why they’re important. This section should be useful, regardless of whether you’re a JavaScript developer or not.
The second part is a short follow-along to help get you started managing your own error messages.
The current state of error messaging
In a perfect world, error messages would be redundant and users would be able to use anything you’ve built a-okay, no problem-o. But errors will happen, and your end-users will run into them.
These errors can stem from:
- Failing validation
- Server-side failures
- Rate limiting
- Borked code
- Acts of god
And when things go wrong, often the client-facing error messaging takes shape in one of two ways:
- Generic errors with no meaningful information, e.g. Something went wrong, please try again later
- Hyper specific messages from the stack trace sent by the server, e.g. Error 10×29183: line 26: error mapping Object -> Int32
Neither are helpful for our end-users.
For our users, the generic error can create a feeling of helplessness and frustration. If they get such a message, they can’t complete an action, and have no way of knowing why the error happened and how (or if) they can resolve it. This can result in loss of end-user trust, loss of customer, or an angry review.
On the other hand, hyper-specific error messages are a leaky abstraction and shouldn’t be seen by our end-user’s eyes.
For one, these kind of errors provide implementation information about our server-side logic. Is this a security concern? probably? I’m no pen-tester.
Secondly, if we’re in the business of crafting engaging user experiences, (and why wouldn’t you be?) our error messages should feel human and be service-oriented. This is a sentiment shared in a number of resource I’ve come across, many of which of I’ve included in a further reading section at the end.
Why should I create sane error messaging?
To help maintain developer sanity
Hunting bugs is hard, and scanning logs is tedious. Sometimes we’re provided with context about why things failed, and other times we aren’t. If an end-user reports a bug it’s important they can present to us as much useful information as possible.
A report from a user that says:
Hi, I was using the app sometime last night updating my profile and all of a sudden it stopped working. The error said something about a validation error, but I don’t know what that means
is much less useful than:
Hi, I was using the app sometime last night updating my profile and all of a sudden it stopped working. The error said «We had trouble updating your details. Your address must be located within the EU» but I live in England
This saves us time and cuts down on red herrings. A clear and specific error message may also help an end-user understand what they themselves have done wrong, and can allow them to fix their mistake.
To help maintain organisation sanity
Sane error messages also yield benefits on an organisation level. For those working in larger companies, copy/messaging may be the responsibility of an entirely separate department. The more places in the code that require copy changes, the easier it is for the copy to get out of sync with your company’s brand guidelines.
Conversely, keeping all of your error messages in a single source makes it much easier for those owning copy to adhere to those brand guidelines.
Other departments, like the support team, may be inundated with support tickets from users. If you’re an engineer, why not reach out to your support team to see how many support tickets could be avoided with improved error messaging.
Fixing the problems with your messaging when a user incorrectly fills out a form, has missing data, or doesn’t have permissions for a specific action could positively impact the lives of the support team.
To help maintain end-user sanity
By providing sane error messaging we hope to not leave our end users feeling helpless.
As described earlier, our messaging should be service—oriented. They should guide our user on how to complete their process, or at least let them know where they can go and get help if the problem is beyond their control.
In Jon Yablonski’s book, the Laws of UX, he describes a psychological concept called the Peak-end Rule:
People judge an experience largely based on how they felt at its peak and at its end rather than the total sum or average of every moment of the experience
In the context of this article, if people become so frustrated that they rage quit your site, their lasting memory of your application is of how frustrating it is to use.
Error messages play a large part in preventing this, as they can act as the final gatekeeper preventing a user who is simply stuck from turning to one so frustrated they quit your app.
If someone is using your product for a transactional purpose like buying an airplane ticket or shopping online, and they’ve been stopped dead in their tracks during a task with no way to continue, the likelihood of them leaving your site for another skyrockets. Another lost customer.
While this is wholly anecdotal, I’ve rage quit sites often from not knowing how to complete a process – either nothing happened when I clicked a button, or I just kept getting vague error messages.
Unless these sites/apps are one of those few ubiquitous platforms (like Google, Instagram, Apple), I likely haven’t have used them since. I’m sure you can even remember a time this happened to you. In fact, I’ll openly welcome pictures of awful error messages via Twitter
Using sane error messaging can help offset this frustration if something doesn’t go right. Surprisingly, creating a useful error message only requires a handful of qualities.
What makes a good error message?
Taken from Microcopy: A complete guide. A useful error message should satisfy these qualities:
- Explain clearly that there is a problem
- Explain what the problem is
- If possible, provide a solution so that the user can complete the process, or
- Point them to where they can go for help
- Make a frustrating scenario as pleasant as possible
This might sound like a lot to cover with just a couple of sentences, but here are some examples of what I deem to be good error messages:
- We’ve limited how many times you can reset your password every hour. You can try again later.
- Please log in to view this profile
- We couldn’t create your profile, only UK residents can use our app.
It’s worth noting that I’m not a UX researcher/designer, just a frontend developer with a keen interest in UX. It may be that my above examples miss the mark on what’s required within your project or organisation.
Saying that, if you’re a frontend engineer, improving your organisation’s error messaging makes for an excellent opportunity to upskill and collaborate with your UXer colleagues.
How can I start writing sane error messages?
I’ve open-sourced a simple tool called sane-error-messages . Running the tool will generate a brand new repo designed to house your default error messaging. You can tweak the default values, add or remove messages, and then publish it to consume within your client facing apps.
sane-error-messages works by aggregating all of your messaging in to a single JavaScript object. The key is an error code, and the value is a corresponding message.
The error codes should be the same codes you receive from your server, such as POSTS_NOT_FOUND or CONFLICTING_USER_RECORD . Your error messaging repo exposes a function to get your error message from an error code.
This approach was inspired by how tools like Cypress handle their error messaging.
As long as your server returns predictable error codes, the server-side implementation doesn’t matter. The following sequence is just one way of implementing sane-error-messages
Having a separate repo becomes more important the more user-facing apps you have.
- The user «views all products»
- The frontend makes a network request
- The network request fails and returns an error code «USER_NOT FOUND»
- The frontend requests the corresponding error message from your error-messages package.
- The frontend applies any relevant contextual information
- The frontend displays this information to the end user.
If you want to try something hands on, you can play with this CodeSandbox. The CodeSandbox fires off a request to a mock server which returns 1 of 12 error codes at random.
The client side will use the error code to retrieve a sane error message from the error messages repo. The client side then displays the error message to the user. If the code doesn’t have a specified message, the generic fallback gets shown (and it sucks).
Some sane error messages in the wild
How to set up your error messages
Note: You can find the repo here. If you come across any problems during the tutorial process you can file a GitHub issue.
Begin by running
yarn global add sane-error-message
to scaffold your project. Doing so will create a brand new module for you to customise with your default error messages.
Your new module uses tsdx under-the-hood to handle all of the module management scripts, such as running, building, and testing.
You can learn more about tsdx here.
In short, the contents of your new package will look like this:
How to consume your error messages
If you created a repo with the name custom-error-messages and published it to npm, you’d be able to consume it within your apps by doing the following:
You can then take all of the error codes that your server-side returns and apply corresponding messages to them.
Once you’re ready, you can publish your tool to NPM, and then consume it from your client-facing apps.
Conclusion
I hope you’ve enjoyed learning about an often overlooked aspect of web development.
I’ve done a bunch of reading to learn about error messaging and I’ve shared some of my favourite resources below. Some are books and others are short articles, but they’re all worth your time.
You can also reach out if any part of the tutorial wasn’t clear, or if you feel I can streamline things. Thanks for reading.
Why can’t the server-side just return these messages?
The server shouldn’t be concerned with any client-facing logic. But if you’re fortunate enough to work with an API that gives useful error codes with each failed request, then you’re nearly there.
Will I need to create an instance of error-messages for every API consumer?
Not necessarily. Because this package can take a list of default messages and codes, as long as it’s in sync with the APIs, your frontends will be able to consume the same package.
In each client-side instance, you can pass through additional error codes, or override existing messages to tailor your frontend messaging.
I think this package should have X or do Y differently
I’m dogfooding this internally at my job, and this is a problem space I’m very new to. I would love to hear of any suggestions, or improvements to the overall architecture or feature-set of sane-error-messages .
Further Reading
Microcopy: A Complete Guide
I mentioned this book a little earlier, and it’s one of my favourites when it comes to making my user-facing products a lot more personable.
The book’s author Kinneret Yifrah, has graciously provided a coupon for 10% off, you can purchase it here.
Coupon code for the eBook: andrico-ebook
Coupon code for the bundle: andrico-bundle
Error messaging guidelines: NN Group
A short article on the importance of sane error messaging which shares some very useful tips on how to create sane error messaging.
- Errors should be expressed in plain language
- Indicate what the problem is
- Suggest a solution
Error Messages (Design basics): Microsoft
An in-depth article that covers both design guidelines messaging practices
Laws of UX
A short book that introduces how a handful of psychology concepts can be used to improve your products UX.