29

It continue to astounds me that, in this day and age, products that have years of use under their belt, built by teams of professionals, still to this day - fail to provide helpful error messages to the user. In some cases, the addition of just a little piece of extra information could save a user hours of trouble.

A program that generates an error, generated it for a reason. It has everything at its disposal to inform the user as much as it can, why something failed. And yet it seems that providing information to aid the user is a low-priority. I think this is a huge failing.

One example is from SQL Server. When you try and restore a database that is in use, it quite rightly won't let you. SQL Server knows what processes and applications are accessing it. Why can't it include information about the process(es) that are using the database? I know not everyone passes an Applicatio_Name attribute on their connection string, but even a hint about the machine in question could be helpful.

Another candidate, also SQL Server (and mySQL) is the lovely string or binary data would be truncated error message and equivalents. A lot of the time, a simple perusal of the SQL statement that was generated and the table shows which column is the culprit. This isn't always the case, and if the database engine picked up on the error, why can't it save us that time and just tells us which damned column it was? On this example, you could argue that there may be a performance hit to checking it and that this would impede the writer. Fine, I'll buy that. How about, once the database engine knows there is an error, it does a quick comparison after-the-fact, between values that were going to be stored, versus the column lengths. Then display that to the user.

ASP.NET's horrid Table Adapters are also guilty. Queries can be executed and one can be given an error message saying that a constraint somewhere is being violated. Thanks for that. Time to compare my data model against the database, because the developers are too lazy to provide even a row number, or example data. (For the record, I'd never use this data-access method by choice, it's just a project I have inherited!).

Whenever I throw an exception from my C# or C++ code, I provide everything I have at hand to the user. The decision has been made to throw it, so the more information I can give, the better. Why did my function throw an exception? What was passed in, and what was expected? It takes me just a little longer to put something meaningful in the body of an exception message. Hell, it does nothing but help me whilst I develop, because I know my code throws things that are meaningful.

One could argue that complicated exception messages should not be displayed to the user. Whilst I disagree with that, it is an argument that can easily be appeased by having a different level of verbosity depending on your build. Even then, the users of ASP.NET and SQL Server are not your typical users, and would prefer something full of verbosity and yummy information because they can track down their problems faster.

Why to developers think it is okay, in this day and age, to provide the bare minimum amount of information when an error occurs?

It's 2011 guys, come on.

gnat
  • 20,543
  • 29
  • 115
  • 306
Moo-Juice
  • 1,378

12 Answers12

22

While there are plenty of examples of bad error messages that simply should not be, you must keep in the mind that it isn't always possible to provide the information you'd like to see.

There is also the concern over exposing too much information, which may lead developers to error on the side of caution. (I promise you that pun was not intended, but I'm not removing it now that I've noticed it.)

Sometimes, there's also the fact that a complex error message is useless to the end-user. Siding with information overload is not necessarily a good approach for error messages. (That may be best saved for logging.)

George Marian
  • 4,390
  • 27
  • 31
21

Developers are not the right people to write error messages.

They see the application from the wrong angle. They are extremely aware of what went wrong inside the code, but are often not approaching the software from the point of view of trying to accomplish something. As a result, what's important information for the developer is not necessarily important information for the user.

8

The charitable view:

  • The developer worked closely with the code and struggled to comprehend someone who didn't have their understanding working with it. As a result they think the error messages are fine, they just don't have a good frame of reference by which to judge them.

  • Intelligent error messages are actually hard to do. Not only writing them but you have to work out everything that might go wrong, assess the likelihood and provide useful information (which almost certainly varies based on the context) back to the person reading the message to allow them to fix it.

  • For most applications it's hard to make a good case for the time to do this sort of thing as well as the next developer would really like because errors don't occur that often. Besides, if you had that extra time shouldn't you spend it stopping the errors rather than reporting on them?

The uncharitable view:

  • Error messages and error handling are dull, there are far more interesting things to be working on and my boss is on my back about the next thing. I understand this code, I'll be fine, the next guy will work it out in the end and I'll be out of here by then so it's not my problem.

The reality is probably somewhere in the middle, though my experience actually tells me it's far more the former than the later - basically it's actually quite hard and takes a fair amount of effort to deal with something which probably won't happen.

Jon Hopkins
  • 22,774
6

Unfortunately, more helpful error messages cost developer time, which equals company money. Products are expensive enough to build as it is. Yes, it would be awesome to have more helpful error messages, and I agree that there should be more useful ones included. However, it's just a fact of life that when you're under a deadline, and money is on the line, you've got to cut something. "Prettier error messages" as managers may see it, will likely be the first thing to go.

Ryan Hayes
  • 20,109
6

I agree that error messages should be as specific as possible.

One reason for generic error messages is probably the use of error codes. When using exceptions you are free to pass all you need in the error message. Using return codes there is no room to encode a columnname. Perhaps the error is handled by a generic function which doesn't know the context and simply translates the error code to a string.

ThomasW
  • 61
4
  • Sometimes too much information can be a security risk; you don't know who's reading the error message
  • Sometimes the operation that threw the exception is so complex that it is impossible to get a meaningful message without negative affects to the speed/complexity of the code
StuperUser
  • 6,163
3

As a general notice, you should consider that any error or exceptional situation is -- exactly that: exceptional. It cross-cuts the planned and designed procedure. It is incompatible to the way things where planned to work. If this wasn't the case, then there wouldn't be any need to bail out with an error abort.

We programmers are trained to care for self-protection of this planned procedure. Thus, we routinely include some sanity checks to verify our assumptions. When these sanity checks fail, we just know that the plan somehow failed...

Your demand -- it may well look like common sense from the user's perspective -- is impossible to fulfil, if you consider the reality of how such a system works. You ask for an orderly statement with well organised and suitable information added. Moreover, you even ask for this presentation to happen in a way which fits into the general application/handling design. Obviously this information exists somewhere in the system. Obviously it even exists there in an orderly and well organised fashion (lets hope so). BUT at the point the error happens, no one ever planned to make this information available. An error always is a partial loss of control. This loss of control can happen on various levels. It could be the system behaving at runtime differently than planned. But it also could be that the actual implementation turned out much more difficult and different in the details then planned, and there was no budged provision to handle this situation satisfactory. This too is a partial loss of control.

To relate this to the concrete example you gave: If, at the point of the error, the name and type of the table column would be known, and in addition the length of the required space, then there wouldn't be any reason for raising an error, wouldn't it? We could just fix the situation and proceed as planned. The very fact that we're forced to raise an error shows us that matters went astray. The very fact that these informations aren't at hand is the exception.

What I'm writing here may seem as self evident and mere common sense. But in reality it is extremely hard to grasp. We constantly try to understand it by applying moral categories -- like there must be a culprit, there must be a bad lazy person which doesn't care for the poor user, there must be a greedy businessmen which did a way to cheap calculation. All of this is completely besides the point

The possibility of loss of control stems from the very fact that we're doing things in a planned and orderly fashion.

Ichthyo
  • 301
2

I work as a support engineer for a software firm and often we see error messages that are new to us. Frequently when I refer these back to our development team, they have to search for the message in the source of the application.

It seems to me that even if it wasn't presented to users, it would safe a lot of time for us if the dev team would add a note to an error message index doc or database whenever they added a new one it would make it far quicker for us to find the cause of customer problems and save them time as well...

glenatron
  • 8,689
2

The problem you're seeing there is actually one of the side-effects of proper encapsulation and information hiding.

Modern systems are extremely complicated. There is little chance that the average developer is able to hold, in his head, a mental model of the entire system from the UI to the raw binary whilst he is coding any particular task.

So, while a developer is sitting down and coding, say, the bit that restores a database file, his mental model is filled entirely with the bits surrounding the act of restoring a database file. He needs to (and I'm guessing, I haven't written this code) read a file, check properties, read versions, backup existing data, choose a merge/overwrite strategy, etc. Quite likely, if there is even a passing consideration to the UI, its in the error string that he writes in an exception handler. Something like:

catch (IOException error)
{
//File is in use
throw new GenericExceptionParsedByTheUIThread("File is in use.");
}

In this example, the helpful information you're asking about in terms of processes that might be using the file, or even other threads in the DB, are completely out of scope (programatically). There may be hundreds of classes that deal with DB files; importing to those classes information about every other process using the files, or functionality to access the file system and look at the other processes running (assuming those processes are even on THIS machine) would result in what is known as a leaky abstraction; there is a direct cost in productivity.

So that's how these kinds of errors can persist in modern days. Obviously, they all COULD be fixed; but in many cases, there's a lot more overhead involved than one might think (in this case for example, you may have to have this function traverse the enumeration of network connections and shares to see if a remote machine is using this database file for some reason) and the cost is far from trivial.

GWLlosa
  • 1,159
2

My favourite was (back in the late 70's) the Univac Fortran IV compiler, when reading non-digits, faithfully announced

The interpretation of meaningless data was attempted

0

I believe the majority of error messages are actually programmer (self) oriented glorified debugging code/printf statements.

Writing user-oriented error messages means knowing who your user is, and anticipating what they will want to know. While in the middle of writing code, a developer is more apt to write an error message useful to themselves, for either debugging the code they are writing at the moment, or useful for the known or predominate Use Case(s).

Switching from writing code to designing a textual portion of the user interface (or user experience) is a context switch. In large applications, such as multilingual applications that could mean it gets handed off to a different person or team (UI, translation) rather than entirely handled by the developer, so unless the developer carefully explains the context of the message, important details can be easily lost.

Of course, checking and verifying error handling is often considered a low priority, as long as errors & exceptions are handled (i.e. caught), not much emphasis is given to it. It's a mentally unrewarding place of the codebase for developers or QA to evaluate, as error conditions often have a negative connotation (i.e. mistake or failure) associated with them.

mctylr
  • 1,163
  • 6
  • 12
0

I think the reason is that error reporting/handling are always done as an after thought. Even when they are not entirely after thought, they're mostly second class citizens in the overall design.

Modern software usually consists of multiple layer. When your error reporting logic is laid down in a rush without too much thought, it's often difficult to gather all the information required to present useful error messages.

For example, the error is caught in the back-end, but it needs some information from higher layers to compose a comprehensive error message. Most good error messages need information from almost all layers (to give us a comprehensive view of what happened in the system). The ideal error message would look like "OK, we first received a string, then it passed through the parser which gave something funny, you might want to look there. Anyway, the thing was passed further down..."

Doing it would often require unnecessary coupling if the error reporting mechanism was not first class citizen during design phase. I guess most people just find that too much work to do for something that doesn't look impressive (who likes to say "See? My program crashed, and the error message is useful!").

kizzx2
  • 277