Phrasing error messages for our users is an integral part of software development. For the user, a good error message can often be the difference between an endless online search for a solution to an inexplicable problem, and a short delay in their workflow. If I had to guess what is the number one reason why I request changes in the pull requests of my team, it would probably be insufficiently informative error messages.
Let's consider the following use case. The user clicks a button that should show a color selector to change the color of some element on the screen. Suddenly there is an error that says: “could not load file”. If I were that user I would scratch my forehead while having a big question mark floating above my head. “What file? I want to change the color not to load a file! What is going on here?” would be my immediate response. This message is very unproductive for the user especially in this scenario where no apparent file operations were performed. The error message does not reflect what exactly went wrong and why, and it doesn’t offer any way of solving the issue. At this point I would fire up ProcMon and start looking for invalid file reads (I guess this is relevant for Windows users).
When asking my teammates to fix an error message I always ask them to imagine that their parent/grandparent/child/pet sees the error message they wrote displayed on the screen. Is it possible for someone who doesn’t know about the internals of the system to understand the problem and act upon it?
Each error message should try and address three key aspects:
The context of where this message occurred.
All the relevant internal information upon which the application had the error.
A possible solution to the problem.
Although in many cases the third is a stretch goal.
Let’s continue with our color selector case. It turns out that the first time the user clicks the color selector the application tries to load a predefined palette file. In the case of our user that palette file was accidentally corrupted by a previous write.
We can provide a little bit of context of where the error occurred by including some explanation to what the application was trying to do in the error message. For example we could emit “Could not load a predefined palette file”. This already covers the first aspect of context but this message is still not clear enough for the user to act upon.
There is often a lot of data we have available in the code segment that emits the message. Let’s add some relevant information to our error message. We tried to load a file hence we have the path to that file. Adding the path to the offending file to the error message can be very beneficial for the user. We most likely have the original error message that was emitted by the framework-specific read function. In some cases adding the original error message into the emitted error message can shed some light on why the failure occurred, and how to fix it (note that it might also be a potential security risk if it discloses the inner structure of your system). Our new error message can be “Could not load a predefined palette file , the following error has occurred: ”.
At this point the error message is already pretty clear and covers the first and second aspects above. A user reading this message would immediately know what went wrong and why.
Sometimes it is possible to suggest a solution to the user by sharing an internal knowledge of the system the user may not be aware of. Let’s assume that in our case deleting the corrupt file will cause the system to fall back to the default configuration and write the file again. If we share this knowledge with the user it may save them the time to fiddle around with the corrupt file.
Hence the full error message can be something like “Could not load predefined palette file , the following error has occurred: . Deleting the corrupt file and restarting the application will recreate the default file”. Or something in this spirit.
To conclude, error messages don’t have to be a source of frustration for your users. Thinking of the three key aspects of context, extra data, and possible resolution while phrasing an error message can result in a happy and content user even when the application fails.
Top comments (1)
Welcome to dev.to :)