Section 13.7.  Error Messages

Table of Contents

13.7. Error Messages

Compose error messages in the recipient's dialect.

An error message is nearly useless if it's unintelligible to those who encounter it. For example, someone who uses a subroutine to load DAXML data[*]:

[*] Sorry...no idea what kind of XML variant DAXML is. The acronym is entirely made up. Still, you'll probably see someone patenting it in the near future.

    use XML::Parser::DAXML qw( load_DAXML );

    my $DAXML_root = load_DAXML($source_file);

will want to see an error message like this:

    File 'index.html' is not valid DAXML.
    Missing "</BLINK>" tag
    Problem detected near "</BLINK</HEAD>".
    Failed at 'DAXML_to_PDF.pl', line 3

An error message like that indicates what the overall problem is (not valid DAXML), why it was considered a problem (Missing "</BLINK>" tag), where the problem occurred (File 'index.html', near "<BLINK</HEAD>"), and which line in the caller's source failed ('DAXML_to_PDF.pl', line 3).

Collectively this informationwhat's wrong, why it's wrong, where in the data, and whence in the codemakes it easy for those who are using your utility to locate and correct their own problems.

Unfortunately, most exception messages are written by developers, and for developers (i.e., themselves). Most often, they're written during the testing or debugging process, so they tend to be written in the language of the developers, using the vocabulary of the implementation. So someone who is using your utility is likely to be confronted with an error message like:

    Invalid token ('<') at 'Acquisition.pm', line 2637

This is very concise (one-fifth the size of the error message suggested earlier) and completely accurate (the problem is indeed the unexpected < of the </HEAD> tag buried in the incomplete </BLINK tag). But it's likely to be of very little help to those who are using your module. They may have no idea what a parser token is, they're faced with thousands of angle-brackets in their data, and they certainly don't want to look through several thousand lines of your module source to try and work out what they did wrong.

So, don't throw exceptions with curt messages that are expressed in the terminology of the implementation:

    # Otherwise parsing has failed...
    else {
        # So report the guilty token...
        die qq{Unmatched token ('$start_token')};

Instead, always croak with a detailed message. And phrase it in the vocabulary of the problem space, using concepts that will be familiar to the caller:


    # Otherwise parsing has failed...
else {
# So grab up to $REPORT_CONTEXT_LEN characters on the same line,
        # from the point in the data where things went wrong...
my ($context) = $source =~ m/ \G [^\n]{0,$REPORT_CONTEXT_LEN} /gcxms;

        # And throw an exception explaining what/why/where/whence...
croak( qq{File '$filename' is not valid DAXML.\n}, qq{Missing "$tag_stack[-1]" tag.\n}, qq{Problem detected near "$context".\n}, qq{Failed}, ); }

    Table of Contents
    © 2000- NIV