Lassie errors

I didn’t invent this term, but boosting the signal gives me a good excuse for a rant against its referent.

Lassie was a fictional dog. In all her literary, film, and TV adaptations the most recurring plot device was some character getting in trouble (in the print original, two brothers lost in a snowstorm; in popular memory “Little Timmy fell in a well”, though this never actually happened in the movies or TV series) and Lassie running home to bark at other humans to get them to follow her to the rescue.

In software, “Lassie error” is a diagnostic message that barks “error” while being comprehensively unhelpful about what is actually going on. The term seems to have first surfaced on Twitter in early 2020; there is evidence in the thread of at least two independent inventions, and I would be unsurprised to learn of others.

In the Unix world, a particularly notorious Lassie error is what the ancient line-oriented Unix editor “ed” does on a command error. It says “?” and waits for another command – which is especially confusing since ed doesn’t have a command prompt. Ken Thompson had an almost unique excuse for extreme terseness, as ed was written in 1973 to run on a computer orders of magnitude less capable than the embedded processor in your keyboard.

Herewith the burden of my rant: You are not Ken Thompson, 1973 is a long time gone, and all the cost gradients around error reporting have changed. If you ever hear this term used about one of your error messages, you have screwed up. You should immediately apologize to the person who used it and correct your mistake.

Part of your responsibility as a software engineer, if you take your craft seriously, is to minimize the costs that your own mistakes or failures to anticipate exceptional conditions inflict on others. Users have enough friction costs when software works perfectly; when it fails, you are piling insult on that injury if your Lassie error leaves them without a clue about how to recover.

Really this term is unfair to Lassie, who as a dog didn’t have much of a vocabulary with which to convey nuances. You, as a human, have no such excuse. Every error message you write should contain a description of what went wrong in plain language, and – when error recovery is possible – contain actionable advice about how to recover.

This remains true when you are dealing with user errors. How you deal with (say) a user mistake in configuration-file syntax is part of the user interface of your program just as surely as the normally visible controls are. It is no less important to get that communication right; in fact, it may be more important – because a user encountering an error is a user in trouble that he needs help to get out of. When Little Timmy falls down a well you constructed and put in his path, your responsibility to say something helpful doesn’t lessen just because Timmy made the immediate mistake.

A design pattern I’ve seen used successfully is for immediate error messages to include both a one-line summary of the error and a cookie (like “E2317”) which can be used to look up a longer description including known causes of the problem and remedies. In a hypothetical example, the pair might look like this:

Out of memory during stream parsing (E1723)

E1723: Program ran out of memory while building the deserialized internal representation of a stream dump. Try lowering the value of GOGC to cause more frequent garbage collections, increasing the size of your swap partition, or moving to hardware with more RAM.

The key point here is that the user is not left in the lurch. The messages are not a meaningless bark-bark, but the beginning of a diagnosis and repair sequence.

If the thought of improving user experience in general leaves you unmoved, consider that the pain you prevent with an informative error message is rather likely to be your own, as you use your software months or years down the road or are required to answer pesky questions about it.

As with good comments in your code, it is perhaps most motivating to think of informative error messages as a form of anticipatory mercy towards your future self.

80 comments

  1. The error number pattern goes all the way back to the early days of the mainframe…and there, it’s not uncommon at all for an I/O error to report an error number and several strings of hexadecimal digits, which the programmer is not only able but expected to look up in the Messages and Codes book.

    It’s just as useful today. There’s a reason I went through and rationalized the messages in Hercules so that every one had a number, and further that the number itself carries information such as what functional part of the system it came from.

    At the other end of the scale, an old story: It is possible to display U FUC UP on an 8-digit, 7-segment display. While it is amusing, it is not particularly helpful.

    1. This is the “critical error prompt” that was printed whenever MS-DOS encountered something that it thought could be fixed with user intervention. Usually there was a terse description of what went wrong whenever MS-DOS printed that infamous prompt. Unfortunately, it wasn’t much help to the hapless users confronted with it–it isn’t obvious, for example, that “volume in drive A not ready” may mean that there’s no disk in the drive. It certainly wasn’t obvious without a knowledge of MS-DOS programming what the prompt means. (Briefly: “Abort” means “stop whatever you were doing and return to the DOS prompt”; “retry” means “try the operation again”; and “fail” means “return this error from the system call that encountered the critical error and pray the caller handles it”; it usually didn’t handle it, though, so in later versions it became “ignore.”)

      Part of it is that, when MS-DOS was originally designed, it had to fit in the one megabyte of space afforded by the 8086 CPU–reduced to 640k of usable RAM by the design of the IBM PC. There wasn’t much space for error messages. It probably would’ve helped to print the error code; at least then there’d be something to look up in the manual. By the time the 386 and extended memory became common, though, there wasn’t much excuse.

      1. it had to fit in the one megabyte of space afforded by the 8086 CPU–reduced to 640k of usable RAM by the design of the IBM PC.

        Even worse than that. While the hardware had a 1MB memory map, and installed system memory was always below 0xa0000, it was pretty rare and expensive to actually have that much. In ye early days, PCs would be equipped with 64KiB or 128KiB of memory and that was it. There really wasn’t much room for a lot of static strings.

        Speaking for myself, I never figured out what the difference between “Abort” and “Fail” were in the actual MS-DOS context. One of the two seemed to get out of it, and I usually had to reboot the machine anyway just to get a usable state back.

        1. “Abort” immediately terminated the program and dropped you back to COMMAND.COM. “Fail” just returned an error code immediately as the result of the DOS I/O call that errored out. (DOS before 3.0 didn’t offer Fail, only Ignore, which immediately returned a success code…)

  2. This term will definitely (sadly) come in handy. It could, for example, be used to describe a recent experience I had with cmake. It actually happens every time I use cmake and anything goes wrong. It “barks” at me: “Hey, something went wrong, how about you check this logfile and all that stuff I created in this folder?”. So I go ahead an to that and time and time again, everything in there is completely useless.

    1. That sounds like the opposite of the Lassie error, in which an error dumps out so much stuff that finding the actual problem can be almost as impossible as if you dumped out nothing.

      I’ve got some code I’m responsible for that tends to communicate in terms of Java stack errors that are a couple hundred lines long, which then defer to another error handle which dumps another couple hundred lines, and that repeats a couple times more. Somewhere in the middle of all this you may be able to figure out that the fundamental error is that the program couldn’t connect to MySQL, but even that manages to get phrased in a rather obscure way (something like “tried to find a connection in the MySQL connection pool but there wasn’t one”… yeah, because it never connected in the first place, but that fact, as near as I can tell, never appears in the log at all).

      Can’t say there aren’t details in the error or that it’s a content-free “error! error!”… but in practice there isn’t much difference!

      1. A Java stack trace is consistently formatted and cleanly readable. You have to know how the “Caused by” chain works, and once you know that, there’s no mystery to it.

        1. I’ve found that Java stack traces are only really useful to someone with intimate knowledge of the source code. To anyone else, they’re basically impenetrable.

          The most recent case I had to deal with was a Tomcat server that had sent out over 500,000 emails over a few hours, each containing full stack traces, which were also flooding the logs. It took three developers to figure out the root cause: someone had inadvertently changed a warning to an error for an edge case not present in their toy database. It took them several hours to escalate it to the only person who actually understood the code that was tickling the bug once a minute for thousands of customer records as soon as it was deployed to a real test service.

          (naturally, the entire dev and QA team that was on the CC list for those emails had set up filters to ignore them years before…)

          -j

          1. The experience of trying to figure out “what went wrong” from a Java stack trace was what convinced me to default to Common Lisp rather than Clojure for my personal projects (which are all I do, these days, since ‘going post-technical’).

  3. I’m not sure about the error number, at least for programs that are certain to be run interactively. When you’re referencing paper documentation, it’s helpful, but on a modern system with plenty of storage, it’s easy enough to include a “would you like more information on this error?” prompt (CLI), or “details” button (GUI). The only exception to this would be failures that leave the software in a state where it may not be able to display any more than the initial error message, probably mostly fatal errors in system software (“kernel panic, error 0xdeaddead, double fault in page fault handler”), or if the program is likely to be run non-interactively, in which case the log should contain a pointer to documentation. But even in the later case, this can be a linguistic, rather than numerical pointer, e.g:

    Out of memory during stream processing, see err-progname-oom-stream(5)

    1. > I’m not sure about the error number, at least for programs
      > that are certain to be run interactively.

      I am.

      Googling “Standardized Error Message ZZ-9450” is a going to narrow things down a lot faster.

      Given that we have modern systems with lots of storage 8 to 10 bytes per error message doesn’t hurt anything, and makes it a LOT easier to search the source code.

      1. And even for closed source programs it gives you a convenient error code to give to the support team, which makes things a lot easier both to tell the support techs what you are seeing, and for the support techs to know which script to follow.

        1. It also has the nice side effect of making error messages more manageable when it comes time to translate them into other languages.

  4. In the v6 era, the standard pattern of messages was
    things that broke “:” what happened “,” what the program did about it.

    I’m not sure it was from the original authors or a back-formation, but I’ve been using
    “load_generator: cannot connect to system under test, halting.”
    ever since.

    1. I like that approach. I had a project recently where I had to develop a systematic error-code system. I have the “what broke”/”what happened” pattern with the message. I the “what broke” part I put not just the system component, but the action/use case that the system was performing, and the “what happened” is the pre-condition/post-condition failure that prevent the action from performing successfully.

      What I’m missing is the “what the program did about it”. That sounds like a very useful piece to add.

  5. It’s probably also helpful to just generate a URL to click that corresponds to the error code. Rust and ZFS both do this.

    Assuming an internet connection, most modern terminal emulators will interpret http/https URLs as a clickable link that brings you right to the web browser and the relevant error message for the really-long-form description and potential solutions.

    Lacking an internet connection, I suppose you just have to hope that locally-installed documentation exists that lists out these codes. Rust succeeds at this, ZFS does not (though the manpages can generally get you to an understanding anyway).

    1. I am getting more and more tired of software that assumes you have an Internet connection, unless the point of that software is to operate over the Internet – web browsers and such. Even then, basic troubleshooting documentation should be available locally, in case the problem is that the software won’t access the Internet to start with. People just seem to assume that Internet and power will be available, or will be returned in a matter of minutes – my experience with Hurricane Rita strongly suggested that was not so. I got power back before I got Internet back, for sure – and if it hadn’t been for a stockpile of material stored on hard drive, I might as well have left that computer turned off. And I can’t count the number of people that, while volunteering at the local library, couldn’t get online because the information they needed to diagnose the issue themselves was only available online (or in my head). We wrote instructions, as best we could – but not only could the patrons screw it up – a lot of times even doing it right didn’t work, due to quirks in their machine, or otherwise. Hell, how often was there CD-ROM driver software only available on a CD, without which the CD-ROM drive wouldn’t work at all? I know *I* had a selection of floppies with the most common ones copied off – even if they weren’t the most up to date, at least I could usually get the drive up enough to use the CD. But J. Random Patron? How likely was it for *THEM*?

      1. > I am getting more and more tired of software that assumes you
        > have an Internet connection, unless the point of that
        > software is to operate over the Internet

        Even then–*a* internet connection doesn’t mean a connection to The Internet. There are plenty of well networked devices that are (allegedly and supposedly) completely air gaped from what we call “the internet”.

      2. “I am getting more and more tired of software that assumes you have an Internet connection, …”
        Agreed, I have reasons to deliberately keep a few machines isolated from any network. All documentation should be accurate, clear and available locally. Using seperate devices to access network based information is as cumbersome as a printed manual. The manual is much less expensive.

        1. Why are you people trying to develop on a machine that’s not networked? It’s 2020, not 1980, and not only does the documentation live online, so does the crates/npm repository you’ll need to get the libraries to do… anything useful, really.

          1. “Security” is a thing for some development. And no machine hooked to the internet is secure.

            I have a client who has separate wiring, switches, and desktops for their internal network, with scripts running to shut it all down and scream bloody murder if they see any outside packets, like from someone plugging in a cable where they shouldn’t. No wifi either.

            1. Well, Jeff mentioned npm, so I think we can safely assume that “security” isn’t in his list of requirements…

          2. Because we aren’t just talking about developers, we should be mostly talking about users – they’re the main unwitting victims of these kinds of useless error msgs.

            And as a developer, I’ve often needed to continue development while offline.

            Hint..
            I sometimes need to go someplace when my car won’t start.
            I sometimes need to eat when the grocery store is closed.
            I sometimes need to communicate when the phones are down.
            I sometimes need light when the power is off.
            I sometimes need a drink when the water is off.

          3. Speaking as a sysadmin and (lately) DBA, this is the sort of thing that makes sysadmins and DBA’s want to drive stakes through the hearts of developers.

            Several concepts I’d like to introduce you to – ‘production system’, ‘security’, ‘change control’.

            No way in hell is anyone going to be opening arbitrary, likely obfuscated, url’s from a production system that is having an issue. If that server is able to reach the internet at all on 80/443 someone has committed a gross oversight already. And any patches/etc, will be coming through another (verified and secure) source.

            I could tell you story about one time someone from my team was patching this old legacy DB server that we’d inherited thanks to a merger. It was taking a while and he got bored and surfed the web…. from the DB server. And managed to infect the server with a virus. That one didn’t end well.

            That was 15 years ago but the memory of that kind of incident stays with you.

            1. >No way in hell is anyone going to be opening arbitrary, likely obfuscated, url’s from a production system that is having an issue

              Which is why the version of this post that is going into my book has this to say:

              Of course, if your program is interactive, you can do better than a bare error code. You might even toss an URL to a browser pointing at the detailed message. But it’s best if that’s a URL pointing to a local cache of documentation, because remote links rot and anyway some of your customers might be air-gapped from the general Internet for good reasons.

              1. >But it’s best if that’s a URL pointing to a local cache of documentation,

                And let even that be adaptive to the user’s internationalization specs:
                file:///./docs/${LANG}/error-codes.html#E1723

                Unzureichender Speicher während der Stream-Analyse (E1723)

                E1723: Das Programm hatte nicht genügend Speicher, als die deserialisierte …

          4. So we supposed to trust others to keep their systems completely secure. You might be happy in China where the government protects you from what it deems negative.

            There are some situations that require no access to any external network for security reasons.

          5. For starters, I’m not a developer. You think *users* don’t need to know why things break? But if I’m feeding data into a program and it breaks with a division by zero error because I didn’t know the program only operated on positive numbers, I want the error message to be better than “ERRDIV0”. Something along the lines of “All inputs must be numeric and greater than 0” is *much* appreciated.

        2. “I am getting more and more tired of software that assumes you have an Internet connection, ”

          Yep. Or not only makes the assumption but imposes it as a requirement – for a non-communicative end use. If for some odd reason I might want to connect my HVAC thermostat to a touchsceen in a different room, running the link up from the living room, halfway to God, then back thru Hades to reach the office or bedroom is just crazy. LOCAL networks, right ?

      3. Hell, how often was there CD-ROM driver software only available on a CD, without which the CD-ROM drive wouldn’t work at all?

        “These are the microfilm instructions on how to use a microfilm viewer.”

        (You’re probably a xennial if you can spot the reference.)

      4. I was ready to reach through the Internet and smack the maintainers of Netpbm when they replaced all the man pages and help messages with useless stubs that said “hey, use a web browser to find the command-line options for these command-line tools”.

        If you actually want to debug command-line tools from the command line, they supply an optional Pascal-in-Perl script that fires up Lynx to display their manpage-in-simple-HTML documentation.

        -j

      5. Even today being able to access the internet relies on drivers that are not part of distributions including windows. Exactly the same as the older CD drivers! New kit will all to often not work without downloading a ‘new’ driver, particularly for wifi drivers, so one is often screwed when recovering from a failure.
        The error messages when trying to fix these types of problem can be equally problematic, and the use of error numbers is not simply a means of cross referencing fuller recovery notes, but also accessing notes in a language one can actually understand! Just been battling hardware where the error messages look very comprehensive but I don’t read Chinese.
        Mind you the alternative PHP approach of simply white screen fatal errors and often not even the logs have a usable error message at all …

      6. I am getting more and more tired of software that assumes you have an Internet connection, unless the point of that software is to operate over the Internet

        If you use the standard mechanism for installing the rust compiler (which requires an internet connection at time of installation) then you get a local copy of the documentation that you can read offline. This should include the Compiler Error index.The biggest hurdle to offline rust IMO is packages. There is a way to do local packages caches, i haven’t played enough with it to comment on how easy it is. Their “Marketplace of ideas” policy on non-core libraries makes sense in the broader sense but it does leave some edge cases wanting.

  6. The thing is, who looks up things in the manual nowadays? It’s much better to put a more expanded explanation into the error message itself. The error code only gets really useful when dealing with the internationalized messages: when you get an error report from a foreign country in a message you can’t read, the error code is the only hint.

    I also find it important to keep and print a whole hierarchy or errors. Here is an example of why it’s important: once upon a time I had an application complain that it couldn’t open its XML configuration file. Yet the file was right there, and even strace showed that it opened the file fine. As I were able to find after decompiling the application, the reason was the the XML file contained an URL of the schema file, and the application tried to download it but failed to open the connection because the machine wasn’t connected to the internet. But the connection exception was caught in the XML library code and replaced with the file opening error. So I’ve developed a class that helps with the nested error reporting: http://triceps.sourceforge.net/docs-2.1.0/guide.html#sc_cpp_errors

  7. Sadly I’m using some software with terrible error message right now:

    “#2608 Object reference not set to an instance of an object.”

    Gah!

  8. IBM has been putting error numbers in their error messages for more than half a century, so you can look it up in the manual. Today it makes sense to simply display a URL that points directly to the documentation which describes what the error means and how to correct it.

    1. No NO NOOOO! Not *EVEN*. Sometimes, the Internet is simply *not* available. It may be because you can’t get the machine connected, it may be because you’re working in a secure facility, it may be because some *bleep* cut a fiber somewhere (and didn’t bother to report doing it!).

      In application documentation is best. Locally stored documentation next (somewhere down /usr/share/doc/ perhaps. Paper copies are good. Online documentation? That just leads to people thinking they can revise the documentation any time they feel like it, moving it because the company got bought out by another company who decides to keep their documentation in a different backend database, or simply deleting it because “nobody uses that any more” or “we don’t support that any more.”

      “Just print a URL” is an amazingly wrong solution!

      1. I don’t think “Just print a URL” is a good idea, but I do think it’s better than just printing the error code. Either way, if the details of the error only exist in an external system (book or Internet) which may not be available.

        Online documentation can usually be downloaded, printed, or sent to the Internet Archive. If the URL naming scheme is sane, then you can usually extract the error code too look up in paper documents (if that’s all you have). Online documentation can also support discussion comments, so that users can get clarification from the publisher about aspects of the documentation that are unclear or incorrect.

        Of course, in application documentation is the best, but the important thing is for the software publisher to inform the users of where the documentation lives, so that they can plan how they will retain access to that information when needed.

        1. Specific URL’s are a lousy idea because of the inevitability of link rot. References to let you search for information, however its storage and organization may have altered, is a much better bet. (anyone ever have to use a specific supplied url to download an old driver or manual? Has that EVER worked?)

          A short message and a reference code are best.

          If local documentation is installed on the server, great. If not, and it’s not really something you can count on, it’s not terrible. Then your admin can search for that reference from their own, online, machines. While they’re also looking at stackoverflow, etc, etc.

      2. In my data centers, fixing a cut fiber would be a far higher priority than troubleshooting an error message in a program. In any case, you’re making a blanket assumption that the documentation included with a program will be of substantially higher quality than the documentation available online. That may be fine if you’re Oracle and you have buildings full of tech writers, but for an open source project the documentation is often collaboratively built by a community of users and co-developers. If you can Duck the error message and be taken straight to an article describing the error and a fix, great — but a link directly in the error message would allow the user to skip the search step.

        This is IN ADDITION TO making the error message readable and useful on its own.

    2. Except you are internet-disconnected or with slow connectivity. Can’t speak about IBM myself, but even for regular, daily, Windozed PC usage, with modern hard-disks having local manual should not be a problem as mentioned by earlier commenters. And somehow, it is for most software.
      Not to say about companies who delete documentation as part of planned obsolence and blocks Wayback Machine robots from archiving it.

  9. I used to call these “Oops!” or “Something went wrong :(” errors, after a form used in Microsoft software. Microsoft products sometimes, but not always, provide error code and irritant information, which you are then expected to look up online. Failing that, the dialog will advise to restart the operation (or the whole computer) and, if the error occurs again, to contact an administrator or tech support.

    The problem is, detailed error messages, like a lot of things in open source, may suffer from critical empathy failure. More than information, most users seek reassurance that they haven’t broken the computer — or worse! And on that axis, “Something went wrong :(” is vastly more helpful than Microsoft’s previous critical error message: “This program has performed an illegal operation and will be shut down.”

    Illegal? My computer did something illegal?! The FBI is cracking down on computer crime lately, what if they find out and I go to Federal pound-me-in-the-ass prison?

    The end user doesn’t need to know that a bug got tickled in Word and it tried to write to an out-of-bounds memory location. All they need to know is — it’s not their fault, most or all of their work has been saved, and they can pick up where they left off by restarting Word.

    1. IIRC, Google, at least at one point, did fairly well with this: Chrome would give some witty, self deprecating, everything is fine error message, and then there would be an “info for nerds” button, or something to that effect, that would give useful details. I’ve not used Chrome proper heavily in quite a while (though just about everything but Firefox has Chromium under the hood these days), so I’m not sure exactly what they’re doing now.

      1. Chrome would give some witty, self deprecating, everything is fine error message, and then there would be an “info for nerds” button, or something to that effect, that would give useful details.

        I’ve always been fond of the Amiga take on this: Guru Meditation — some variant of which is still in use in some systems, for example if Reddit’s internals crash you might see a “Guru Mediation” [sic]. It says: The cause of this error is accessible only to the enlightened, as end users wouldn’t be able to do anything about it anyway. save hard-reboot their machine. And yes, I know the JoyBoard story.

    2. But the sysadmin needs a lot more than this. There should be a place to get that kind of scary, nerdy information without having to use a debugger (which they probably don’t have and aren’t allowed to install). So by all means, provide the simple, reassuring answer, but have the details available, even if they’re hidden behind an “advanced” button.

  10. In order to print an error message describing what went wrong, your program has to know what went wrong. Sounds silly, but coding style rules can make it inconvenient to structure the code so this is possible. For instance, one might write
    if(!PREREQ_1) {
    fprintf(stderr, "Prereq 1 not met\n");
    return NULL; }

    if(!PREREQ_2) {
    fprintf(stderr, "Prereq 2 not met\n");
    return NULL; }

    and so forth to check that it is safe to begin munging data. But if the programmer is only allowed one return statement, everything ends up chained in the else{} block of the preceding check, and the actual payload code is nested N levels deep and indented to an unwieldy extent. So what ends up happening is that there is a single initial check of the form
    if(!(PREREQ_1 && PREREQ_2 && ... && PREEREQ_N)) {
    fprintf(stderr, "Prereqs not met\n"); }
    else {

    At this point he knows know that an error occurred, and has alerted the user instead of performing a potentially unsafe computation. But he’s lost the details of what went wrong, and adding a lot of logic to the error case to figure out which error occurred is not likely to be seen as a good use of time, since he’ll take the same action no matter what: print a warning to stderr and try to avoid breaking anything else before reaching the return.

    1. Why not something like

      if not prereq1, append err1 to list errs
      if not prereq2, append err2 to list errs

      for e in errs
      print(e.errmsg)
      return

  11. I wish there were some other term besides “Lassie”. Lassie is a lovable, empathetic creature. Everyone loves Lassie.

    The people who make a craft of writing unhelpful or anti-helpful error messages ought to be given a name that will scar them and follow them around for life.

    *cough* Microsoft, Intuit *cough*

    1. And Lassie was useful after all.
      I second the idea. Unfortunately, No one in this thread seems to propose any better ones.

    2. In-universe, humans could understand Lassie’s barks of distress as if they were speech.

      So maybe “Something went wrong :(” with an error code is the true Lassie error, with techies playing the role of Timmy’s family, able to comprehend the “barks”.

      Oh well. “Lassie errors” is catchy, if somewhat inaccurate — much like “Yoda conditionals”.

  12. The (notoriously unreliable, in my experience) Archive tape drive software used to love throwing out “Error 46.” Which wasn’t among the list of error codes Archive documented.

    Why only document *some* of the error codes? And “46” popped up regularly…

    Then there were the early versions of IBM OS/2, which would throw “can’t find COUNTRY.SYS” if it saw something it didn’t like during the boot sequence. Since the file was right there, and properly configured, my best guess was it was throwing some undocumented error, and “can’t find COUNTRY.SYS” was the last message in the error list. I expected better from IBM…

    1. I once spent a merry hour debugging a Lotus Notes problem on classic MacOS. The error message was “servername: not a valid TCP/IP host”. The actual error was “hard drive name contains ‘!’, so I can’t look up paths”.

      -j

  13. My preferred method is having some kind of err() function in the project that takes an enum value, which has its pros and cons.

  14. We ran into a classic case of this back at Rutgers in the 80s. We supported one ex-Stanford AI researcher with the SAIL language. He came in one day with a failed compilation and the error message “Dryrot at Bletch.”
    So we took the compiler source and searched for “Dryrot at Bletch.” Right next to the print was a COMMENT “Luser has forgotten a semicolon.”

  15. What would be the best way for robust error reporting for mobile apps, which usually lack stderr (outside of debugging environments). For example recently I explored Android development and found it a nightmare compared to desktop development, especially because a mere orientation change in the device can destroy your Activity and you need to code to accommodate every possible configuration change on the device. Also it may be impossible to figure out what can possibly go wrong in each and every kind of device out there, on which you app may run. Also a program that works perfectly on the emulator can crash with great ugliness on an actual device.

    I have found from my limited experience that you can anticipate and catch the user errors or normal invalid data that your program expects. But what about unexpected runtime errors that occur due to some bug that has been overlooked by the developer or memory leak etc. Most of the unexpected crashes and hard-to-diagnose (from user point of view) errors are usually of this kind (I found NullPointer errors in Java and segmentation faults in C/C++ the worst of this kind, usually traceable to an inane assignment statement somewhere). I think the first kind, simple error handling of predictable situations can be easily managed from the programmer by anticipating the possible error criterion, but can a developer account for all the possible situations that can lead to program errors/crashes? Won’t that make the program littered with error-checking code in every possible statement that can fail, making the code far more clumsy and unmanageable?

  16. The guidance I give on error messages is this little scene:

    it is 2am, and your phone just rang. Someone is going to read an error message to you and ask “what should I do?” If the error message is “file not found”, what will you tell them?

    A better message would be: “Unable to start service because configuration not found because file /usr/service/config/startup.cfg not found.”

    Do your error messages pass the 2am phone test? Some day mine all will. One message at a time.

  17. I like the cookie solution. Error messages do get translated to various human languages these days, and everybody uses Google to solve problems. And trying to translate an error message back to English *while also trying to guess the original wording* in order to Google it is no fun. Actually, if the translator did a proper job and it is a good idiomatic translation, not Franglais / Deunglish, it gets tough to try to guess the original wording. And even Google Translate is dangerously good these days… So it is better to have some kind of unique ID that never gets translated.

    1. This is about the best argument I’ve seen so far for user-visible error numbers. I’m predisposed to dislike them, however, because I’ve generally found that software that prints error numbers tends not to print other useful info.

      “Error 3. RTFM for more info.”

  18. Hal Finney once wrote a Basic interpreter for a 2K 8 bit embedded system. It was so tight on memory the only error message was:

    EH?

    He thought it was a great joke, and we all ribbed him about it for quite a while afterwards.

  19. Regarding syntax errors: here the problem with having good error messages may be caused by the type of the parser used. LALR parsers (yacc / bison) have notoriously bad error messages. Recursive descent are handcrafted. PEG parsers are hard to reason about what language they generate. Table based parsers (eg Marpa) are not popular.

    1. ANTLR (an LL parser generator) aims to improve the error messages. But fundamentally, there shouldn’t be any reason why YACC couldn’t do it better. After all, a LALR parser has more information at any given time than an LL parser, because it had parsed farther. It’s just that nobody bothered with a way of doing the better error reporting in YACC. ANTLR allows you to define the error points that generate the specific messages. There is really nothing preventing YACC from doing the same.

  20. Why aren’t you working for a real tech company but instead begging on patreon like some Indian sadhu ?
    Why to bury a smart mind like you in a museum of archaic OSes all day playing necrophilia of BSD and old junk ?
    I’ll tell everyone what I think is why. The american society has failed its people, failed to provide them with descent avenues to live and express themselves and to live honestly.
    This is really sad. Lassie’s body won’t even be post mortem-ized in the current situation…

    Either that or you are CIA.

  21. while this is all true, it just forces my mind onto an internal rant about the converse problem — Lassie (l)users.

    you know, the kind that see an error message on their screen and suddenly lose all facility for reading comprehension, straight back to pre-K levels.

    i’m on the mailing list for my organization’s help desk, and one of our users just today asked the equivalent question of “why am i getting this”. where “this” was an office 365 mail-cannot-be-delivered because username-does-not-exist message; in fairness to microsoft, it’s about the most readable, most helpful, most user-friendly error message i’ve ever seen generated. it tells you _right there_ in big, semi-bold sans serif that “(this user name) does not exist at (this domain)”.

    and the recipient was supposed to be another, in-organization, coworker, so just using outlook’s built in address book would’ve prevented or resolved the entire issue. yet the solution actually reached for was “email help desk and ask why i got this message”.

    1. Well, if you know – or even suspect – that “username does not exist” is a false statement, then “Why am I getting the error ‘mail-cannot-be-delivered because username-does-not-exist’?” is a perfectly cromulent question. Even if it’s technically true, because of case-significance or a missing period after the middle initial or some such, then it’s still a reasonable question.

      1. it’s a sort-of reasonable question, but could have been resolved with a phone call to the coworker, or a by-name lookup in the corporate email directory built into the email client. either of which should have been prompted by the awareness that we’ve long since stopped using nicknames and diminutives in email addresses, and now insist on full legal names instead.

        and on the original subject, key codes: great for searching my own source code to find the exact spot an error’s originating from. i think that point’s been made before already, but it’s good enough i feel like seconding it.

  22. “Lassie error”

    A term I’ve never heard before but immediately understood and laughed when I read it. Fantastic.

    By its name, you know it.

    Also, key codes: great when doing a websearch for someone who’s encountered the problem before.

  23. SQLite has a great one: “bad parameter or other API misuse”

    It came up recently because with SQLite you can create a unique index, but then you need to know that it’s your job to also create a unique constraint. If you don’t, you get this error every time you insert a duplicate value. Fun times. Well, not the “Going To Disneyland” kind of fun, more like the “Taking progressively larger doses of poison to become immune” kind of fun. But fun.

  24. Way back when I worked on the Psychtoolbox I finally settled in a three-sentence rule for errors. The first sentence should state what caused the error. The second sentence should state how to fix it. The third sentence should state how to learn more.

    It was a flexible rule. Not every error message needed all three of those, the point was that when writing the error message I should always consider which of those would be helpful. For example, if the user passed an integer where a string was expected, just saying that alone should be enough.

    It is helpful to keep in mind that from that standpoint of the users, their priority is to remedy errors as fast as possible with the least effort. The message should be designed with that in mind. Seems like sometimes programmers lose track of that purpose when constructing error messages.

    1. >The first sentence should state what caused the error. The second sentence should state how to fix it. The third sentence should state how to learn more.

      I had forgotten this one. It’s a good heuristic.

Leave a Reply to Christopher Smith Cancel reply

Your email address will not be published. Required fields are marked *