6 Error messages

An error message should start with a general statement of the problem then give a concise description of what went wrong. Consistent use of punctuation and formatting makes errors easier to parse.

(This guide is currently almost entirely aspirational; most of the bad examples come from existing tidyverse code.)

6.1 Problem statement

Every error message should start with a general statement of the problem. It should be concise, but informative. (This is hard!)

Use stop(call. = FALSE), rlang::abort(), Rf_errorcall(R_NilValue, ...) to avoid cluttering the error message with the name of the function that generated it. That information is often not informative, and can easily be accessed via traceback() or an IDE equivalent.

6.2 Error location

Do your best to reveal the location, name, and/or content of the troublesome component. The goal is to make it easy as possible for the user to find and fix the problem.

(It is often not easy to identify the exact problem; it may require passing around extra arguments so that error messages generated at a lower-level can know the original source. For frequently used functions, the effort is typically worth it.)

If the source of the error is unclear, avoid pointing the user in the wrong direction by giving an opinion about the source of the error:

If there are multiple issues, or an inconsistency revealed across several arguments or items, prefer a bulleted list:

6.3 Hints

If the source of the error is clear and common, you may want provide a hint as how to fix it:

Hints should always end in a question mark.

Hints are particularly important if the source of the error is far away from the root cause:

Good hints are difficult to write because, as above, you want to avoid steering users in the wrong direction. Generally, I avoid writing a hint unless the problem is common, and you can easily find a common pattern of incorrect usage (e.g. by searching StackOverflow).

6.4 Punctuation